Difference between revisions of "Scripting"

From Team Fortress Wiki
Jump to: navigation, search
(This page reads like a how-to not an encyclopedic article.)
m
(370 intermediate revisions by more than 100 users not shown)
Line 1: Line 1:
Note that the word "scripts" as it is used on this page should not be confused with the .scr files that modify server behavior.
+
{{Quotation|'''The Engineer''' after using his [[sentry jump]] script|This thing ain't on auto-pilot, son!|sound=Engineer wranglekills01.wav}}
 +
'''Scripting''' is the use of configuration files ({{code|.cfg}}) mainly to create new keybinds and aliases, automating complex behaviors and [[console]] command sequences. Unlike [[hacking]], scripting is built into ''Team Fortress 2'' and is not banned by VAC ([[Valve Anti-Cheat]]). Uses of scripting vary from simply binding a key to a command to self-referential loops and nested aliases that redefine one another. Any functionality that can be created with scripting can also be accomplished without it, but scripting allows these functionalities to be used in the heat of battle.  
  
For common scripting questions, please visit the [[Scripting Faq]] page.
+
== Scripting Commands ==
 +
The following is a list of commands which have no use apart from scripting; they do not influence gameplay directly.
  
==A Brief Overview of Scripts==
+
=== bind ===
===What are binds?===
+
{{Main|vdc:bind|l1=bind}}
Scripts in TF2 are known by several names, including "binds," "keybinds," and "bindings."  Binds are a way to attach (or ''bind'') game commands to a key.
+
The simplest command is the bind command. It will cause a certain key to execute a certain action, whether that action is a setting, a command, or a script.
  
===Aren't binds cheating?===
+
<pre>bind [KEY] [COMMAND]</pre>
Not in many people's opinion. Think of it this way: binds allow you to do things you could have done easily, but faster. Everyone has easy access to binds, so they don't give you any advantage over other people. Also, the developers of the put this feature in deliberately and allow it to happen (and they really don't like cheating because it is a multiplayer game) so it is seen as a legitimate use of the game.
+
Quotes can be optionally placed around the key and/or the command. However, the commands will need to have quotes when it has spaces in between the values and the command, so that the console can interpret it as one command. An example would be bind mouse1 "say texthere", where quotes are needed around "say texthere" because of the space between the two phrases.
  
===Where are binds located?===
+
<pre>bind [KEY] "[COMMAND 1];[COMMAND 2];[COMMAND 3]"</pre>
The game itself stores binds in the file:
+
Quotes can be optionally placed around the key, but must be present around the commands, as the console will not interpret consecutive commands if quotes are not present.
<pre><Steam Folder>\SteamApps\<account_name>\team fortress 2\tf\cfg\config.cfg</pre>
 
The commands in this file are executed every time the game starts.  Even though the user can modify this file in any text editor, it's often a good idea to add custom binds elsewhere.  To this end, there is another file where users can add their own binds:
 
<pre><Steam Folder>\SteamApps\<account_name>\team fortress 2\tf\cfg\autoexec.cfg</pre>
 
This file does not exist by default, but can be created by the user.  As with config.cfg, the autoexec.cfg is just a simple text file that can be edited by the user.  And just like config.cfg, the autoexec.cfg file is executed whenever the game starts.
 
  
When you create your autoexec.cfg file in your favorite text editor, be sure your text editor isn't tacking on a ".txt" to the end of the filename as is default with notepad (i.e. autoexec.cfg.txt), as that will not be auto-executed. It might not even be accessible from the console!
+
''Note:'' The command <code>say "Example Text"</code> is correct, but <code>bind <KEY> "say "Example Text""</code> is not. This is because the quotes are misinterpreted, and quotes inside of quotes are unnecessary due to commands automatically stopping at every semicolon.
  
A good way to make sure that your autoexec.cfg file is not named incorrectly is to have your operating system show all file extensions of known filetypes. Googling found this page [http://www.granneman.com/techinfo/windows/showextensions/] which gives good graphical instructions on exactly how to do that.
+
When a key is bound to a string starting with a plus, the same command(s) will be executed when the key is released, except the first plus will be replaced with a minus. For example, <code>bind w +forward</code> will make pressing {{key|W}} execute <code>+forward</code> and releasing {{key|W}} execute <code>-forward</code>. Note that this only effects the first command, and other commands will not be negated. See [[#alias|alias]] for more information.
 +
This bind will make the player move forward while they have {{key|W}} held down.
  
===Using Scripts===
+
=== toggle ===
Putting a script in autoexec.cfg will apply that script to every class, so if there's a class you don't want to use the script, you have to counter it in the specific <class>.cfg file.
+
This command allows a cvar to be toggled between two or more values. If no values are specified, defaults to toggling between 0 and 1.
Also, putting a script in <class>.cfg will also apply it to every class, so you have to counter it in the other classes too. For example, if you bind 'mouse2" to "reload" in 'engineer.cfg', but you want it to be bound to something else in the other classes, you have to re-bind "mouse2" to "something else" in all the other '(class).cfg' files.
 
  
===Syntax===
+
<pre>toggle tf_bot_quota normal fill match</pre>
For any key binding or alias binding script within the Source engine developer console, the following format must be followed:
 
COMMAND <argument1> <argument2>
 
  
Quotation marks are NOT necessary for binds and aliases with singular arguments, such as '''bind 1 slot1'''.
+
==== bindToggle ====
However, if you wish to create a bind whose arguments may have multiple commands or parameters, you must enclose the plural arguments with quotation marks and separate the individual components with semicolons, such as '''alias melee1 "slot3; +attack"''' (creates a new "command," the alias "melee1," to automatically switch to your melee weapon and start attacking).
+
BindToggle may be used to bind a key to toggle a cvar between 0 and 1. It cannot be used for values besides 0 and 1.
  
Examples:
+
<pre>bindToggle o sv_cheats</pre>
 +
 
 +
=== incrementvar ===
 +
This allows for variables to be increased or decreased repeatedly by a set amount.
 +
 
 +
<pre>bind MWHEELUP "incrementvar fov_desired 75 90 1"
 +
bind MWHEELDOWN "incrementvar fov_desired 75 90 -1"</pre>
 +
This will cause the [[field of view]] to increase when scrolling up, and to decrease when scrolling down
 +
:''Note:'' Incrementvar will cause the value to wrap around if it gets too large or too small. In this example, once the field of view hits 90, it will drop down to 75, and vice-versa.
 +
 
 +
=== alias ===
 +
{{Main|vdc:alias|l1=alias}}
 +
An alias allows multiple commands to be referenced by a single command. This is effectively shorthand, and it is most useful when a series of commands need to be called multiple times. Alias names cannot contain spaces. They may contain underscores, numbers, symbols, and are not case-sensitive (only when being created, when removing an alias it is case-sensitive).
 +
 
 +
After running the command <code>alias foo "echo bar"</code>, typing <code>foo</code> in the console will execute <code>echo bar</code>.
 +
After running the command <code>alias foo</code>, typing <code>foo</code> in the console will no longer do anything. If the alias was created with uppercase letters (such as <code>alias fOO "echo bar"</code>), typing <code>alias foo</code> will not remove the alias, but <code>alias fOO</code> will.
 +
 
 +
Aliases may begin with a plus or minus character. This allows them to be used in conjuction with <pre>bind</pre> to negate several commands when a key is released. For example, this script allows a player to move diagonally with a single key:
 +
 
 +
<pre>alias +diagonal "+moveleft; +back"
 +
alias -diagonal "-moveleft; -back"
 +
bind z "+diagonal"</pre>
 +
 
 +
Releasing Z will execute <code>-diagonal</code> in this script, whereas simply typing <code>bind "z" "+moveleft; +back"</code> would result in the game never running <code>-back</code> when the player releases the key. This results in the player moving backwards continuously.
 +
 
 +
=== exec ===
 +
This command will execute another file. This means that complex scripts can be stored in other files, so as not to clutter up more general files.
 +
 
 +
<pre>exec autoexec.cfg</pre>
 +
This script will execute the player's autoexec script.
 +
 
 +
=== echo ===
 +
This command will cause text to be printed to the console. This is very useful for debugging.
 +
 
 +
<pre>echo Scripting is; echo very useful</pre>
 +
This will print out <code>Scripting is</code> and <code>very useful</code> on ''two separate lines''. This is because a newline is added to the end of any text passed to <code>echo</code>. Spaces are only parsed if they are between words, or if the echoed text is between quotes, as in the next example:
 +
 
 +
<pre>echo " Scripting is very useful.  "</pre>
 +
The extra spaces will be printed out, since the string is delimited by quotation marks.
 +
:''Note:'' It is not possible to print out the " character, as its meaning will be misinterpreted. However, you can print single quotes: that is, the ' character.
 +
:''Note:'' Echo occasionally will misprint strings that are not delimited by quotation marks. As a general rule of thumb, it is better to enclose what you wish to print within quotation marks. It also makes it easier to read for humans.
 +
 
 +
=== wait ===
 +
This command will make the game wait a given number of frames before executing the next command.
 +
:'''Warning: Wait commands are disabled on certain servers. This will cause certain scripts to fail, and may (in semi-rare cases) cause the game to crash. See [[#Wait-testing|Wait Testing]] for help to protect against this.'''
 +
 
 +
<pre>echo Why did the chicken cross the road?;wait 300;echo To get to the other side!</pre>
 +
This script will wait 300 frames (1 second at the default max FPS) before printing the punchline.
 +
 
 +
== Class-specific CFG Files ==
 +
When switching to a certain class, the game executes the corresponding CFG file (if it exists), named after the given class.
 
<pre>
 
<pre>
COMMAND  <argument1>    <argument2>
+
scout.cfg
alias    qBetween1and2  "slot2; wait 10; slot1"
+
soldier.cfg
bind    1              qBetween1and2
+
pyro.cfg
 +
demoman.cfg
 +
heavyweapons.cfg
 +
engineer.cfg
 +
medic.cfg
 +
sniper.cfg
 +
spy.cfg
 
</pre>
 
</pre>
Note: I spaced the arguments out so you could see what applies to what, don't do this when you script.
+
This automation lets the player have different keybinds and game settings for each class.
  
===How are simple binds written?===
+
== Launch Options ==
A simple bind takes the form of ''bind <key> <command>''. For example, if we wanted to activate our primary weapon whenever we press the '''1''' key, then we could write a bind that looks like this:
+
Launch options can be used to change how TF2 runs, both performance wise and functionality wise. Please see {{vdc|Command Line Options|Command Line Options}} for a comprehensive list of launch options
<pre>bind 1 slot1</pre>
 
:("slot1" is the command to activate your primary weapon)
 
Each bind must be written to a separate line in the autoexec.cfg file.  For an example of basic keybinds, look at your config.cfg file in any text editor.  For a list of useful commands, see the "Console Commands" section of this page.
 
  
===How are complex binds written?===
+
== Set Launch Options ==
Complex binds take the same form as simple binds, except that they execute multiple commands when you press the key. Each command must be separated by a semicolon (''';'''). For example, let's take a look at this complex bind for an Engineer (swiped from Patty on the TF2 boards):
+
[[File:Setting Launch Options.png|thumb|none|A visual guide on how to set launch options (indicated by the red circles).]]
<pre>bind "q" "build 0; wait 50; +attack; wait; -attack; slot1"</pre>
+
# Right-click on the game title under the '''Library''' in Steam and select '''Properties'''.
:This bind attaches a series of commands to the '''q''' key.  When the user presses the '''q''' key, the following series of commands is executed in order:
+
# Under the '''General''' tab click the '''Set launch options...''' button.
:*'''build 0''' tells the game to enter the build mode for a dispenser
+
# Enter the launch options you wish to apply (be sure to separate each code with a space) and click '''OK'''.
:*'''wait 50''' tells the game to wait 50 frames before executing the next command
+
# Close the game's '''Properties''' window and launch the game.
:*'''+attack''' tells the game to start and continue the primary attack (we will learn more about plus and minus commands a little later)
 
:*'''wait''' tells the game to wait a moment before executing the next command
 
:*'''-attack''' tells the game to end the primary attack
 
:*'''slot1''' tells the game to activate the primary weapon (in the case of the Engineer, this is the shotgun)
 
  
===How do plus(+) and minus(-) commands work?===
+
=== Window Options===
Plus and minus commands are two-state commands.  The plus state is executed (and continues to execute) while the key is pressed. The minus state executes when the key is released. For example:
+
Note that these may incorrectly setup an improper video mode not preferred by the material system, reducing performance. Where possible, you should use the in-game settings instead.
<pre>bind "c" "+duck"</pre>
+
====Resolution====
:This bind causes the player to duck and remain crouched as long as the '''c''' key is pressed. When the '''c''' key is released, the player stands again.
+
Launch Option: '''-w # -h #'''
It is important to note that, although the '''-duck''' command is never explicitly mentioned in the bind, it will still be executed upon release of the key.
+
:''Description:'' Forces the game resolution width and height in pixels.
 +
====Refresh Rate====
 +
Launch Option: '''-freq #'''
 +
:''Description:'' Forces the game refresh rate in Hz.
 +
====Windowed Mode====
 +
Launch Option: '''-windowed'''
 +
:''Description:'' Launches the game in windowed mode.
 +
====Borderless Windowed Mode====
 +
Launch Option: '''-noborder'''
 +
:''Description:'' When in windowed mode, remove the window border to allow for borderless fullscreen mode, as opposed to exclusive fullscreen mode.
 +
====Fullscreen Mode====
 +
Launch Option: '''-fullscreen'''
 +
:''Description:'' Forces the game resolution width and height in pixels.
  
===What are aliases and how are they written?===
+
===Peripheral Support===
Aliases are similar to binds except that, instead of binding a series of commands to a key, they allow the user to name a series of commands. That name can later be used in place of the series of commands. Using the Engineer example above, for example:
+
====Disable Joystick Support====
<pre>
+
Launch Option: '''-nojoy'''
alias "buildDispenser" "build 0; wait 50; +attack; wait; -attack; slot1"
+
:''Description:'' Prevents the joystick system from loading, improving start-up time and memory usage. Don't use this if you intend to use a joystick with the game.
bind "q" "buildDispenser"
+
====Disable Steam Controller Support====
</pre>
+
Launch Option: '''-nosteamcontroller'''
:This alias followed by a keybind begins to show the power of the scripting system for TF2. We have created an alias called '''"buildDispenser"''' (although we could just as easily have called it "Fred" or "Snuffalupagus" or whatever we chose). Whenever we call the name of this alias, it executes the commands to which it's bound.  Then we bind the '''q''' key to the alias name. Whenever we press the '''q''' key, that alias is executed.
+
:''Description:'' Prevents the Steam controller system from loading, improving start-up time and memory usage. Don't use this if you intend to use a Steam controller with the game.
Why are aliases more useful than binds?  We'll get into that a little more deeply later, but imagine if you wanted to bind that same series of commands to multiple keys. Instead of typing the series again for each key, you can now just bind the alias name to each key.  This way, if you want to change something in that series of commands, you only have to change it in one place.
+
 
 +
===Software Support===
 +
====Disable SourceTV====
 +
Launch Option: '''-nohltv'''
 +
:''Description:'' Disables [[SourceTV]] support, improving memory usage. Don't use this if you host SourceTV on your client.
 +
====Disable Quicktime====
 +
Launch Option: '''-noquicktime'''
 +
:''Description:'' Disables [[w:QuickTime|QuickTime]] support, improving memory usage. Don't use this if you required QuickTime support, such as for when exporting .MOV files.
 +
 
 +
===Engine Options===
 +
===Disable Intro Video===
 +
Launch Option: '''-novid'''
 +
:''Description:'' Removes the Valve intro video shown when the game is started, improving loading times.
 +
====Change Beam Particle Limit====
 +
Launch Option: '''-particles #'''
 +
:''Description:'' Limits the number of beam particles. Set # to '1' to (a limit of 512) to improve memory usage.
 +
====Precache Font Rendering====
 +
Launch Option: '''-precachefontchars'''
 +
:''Description:'' Precaches font rendering for common characters, improving rendering time.
 +
====Disable Texture Streaming====
 +
Launch Option: '''-no_texture_stream'''
 +
:''Description:'' Disables using lower quality textures whilst higher quality versions load, instead favouring to always instantly load the higher quality versions. Disabling texture streaming will have a performance impact on systems under video memory pressure.
 +
 
 +
===DirectX Version (Windows Exclusive)===
 +
Launch Option: '''-dxlevel #'''
 +
:''Description:'' Sets the DirectX Version used by the game; accepts many values but only '81' and '100' should be considered.
 +
::'-dxlevel 100' uses DirectX 9 and Pixel Shader 3.0, and hardware is used to determine the system's graphics capabilities.
 +
::'-dxlevel 81' is the most stable version of DirectX 8 and uses Pixel Shader 1.1. It typically has more performance than DirectX 9 versions but has a reduced feature set so should be avoided if the performance increase is not absolutely necessary.
 +
:Note: After launching the game with this once, the game should then be closed and it should be removed from the launch options in order to properly set the related configuration files.
 +
 
 +
== List of key names ==
 +
Hover over a key to see its scripting name. Names are not case-sensitive.
 +
{|
 +
! width="45%" <!-- Main Keyboard -->|
 +
! width="03%" <!-- Spacing      -->|
 +
! width="25%" <!-- Special Keys -->|
 +
! width="01%" <!-- Spacing      -->|
 +
! width="25%" <!-- Keypad 1      -->|
 +
! width="05%" <!-- Keypad 2      -->|
 +
|-
 +
|
 +
{{tooltip|{{key|ESC}}|ESCAPE}}
 +
{{tooltip|{{key|F1}}|F1}}
 +
{{tooltip|{{key|F2}}|F2}}
 +
{{tooltip|{{key|F3}}|F3}}
 +
{{tooltip|{{key|F4}}|F4}}
 +
{{tooltip|{{key|F5}}|F5}}
 +
{{tooltip|{{key|F6}}|F6}}
 +
{{tooltip|{{key|F7}}|F7}}
 +
{{tooltip|{{key|F8}}|F8}}
 +
{{tooltip|{{key|F9}}|F9}}
 +
{{tooltip|{{key|F10}}|F10}}
 +
{{tooltip|{{key|F11}}|F11}}
 +
{{tooltip|{{key|F12}}|F12}}
 +
 
 +
{{tooltip|{{key|` &nbsp;}}|`}}
 +
{{tooltip|{{key|1}}|1}}
 +
{{tooltip|{{key|2}}|2}}
 +
{{tooltip|{{key|3}}|3}}
 +
{{tooltip|{{key|4}}|4}}
 +
{{tooltip|{{key|5}}|5}}
 +
{{tooltip|{{key|6}}|6}}
 +
{{tooltip|{{key|7}}|7}}
 +
{{tooltip|{{key|8}}|8}}
 +
{{tooltip|{{key|9}}|9}}
 +
{{tooltip|{{key|0}}|0}}
 +
{{tooltip|{{key|-}}|-}}
 +
{{tooltip|{{key|{{=}}}}|{{=}}}}
 +
{{tooltip|{{key|← Backspace}}|BACKSPACE}}
 +
 
 +
{{tooltip|{{key|TAB}}|TAB}}
 +
{{tooltip|{{key|Q}}|Q}}
 +
{{tooltip|{{key|W}}|W}}
 +
{{tooltip|{{key|E}}|E}}
 +
{{tooltip|{{key|R}}|R}}
 +
{{tooltip|{{key|T}}|T}}
 +
{{tooltip|{{key|Y}}|Y}}
 +
{{tooltip|{{key|U}}|U}}
 +
{{tooltip|{{key|I}}|I}}
 +
{{tooltip|{{key|O}}|O}}
 +
{{tooltip|{{key|P}}|P}}
 +
{{tooltip|{{key|[}}|[}}
 +
{{tooltip|{{key|]}}|]}}
 +
{{tooltip|{{key|\ &nbsp; &nbsp; &nbsp;}}|\}}
 +
 
 +
{{tooltip|{{key|⇪ Caps}}|CAPSLOCK}}
 +
{{tooltip|{{key|A}}|A}}
 +
{{tooltip|{{key|S}}|S}}
 +
{{tooltip|{{key|D}}|D}}
 +
{{tooltip|{{key|F}}|F}}
 +
{{tooltip|{{key|G}}|G}}
 +
{{tooltip|{{key|H}}|H}}
 +
{{tooltip|{{key|J}}|J}}
 +
{{tooltip|{{key|K}}|K}}
 +
{{tooltip|{{key|L}}|L}}
 +
{{tooltip|{{key|;}}|SEMICOLON}}
 +
{{tooltip|{{key|' &nbsp;}}|'}}
 +
{{tooltip|{{key|Enter ↵}}|ENTER}}
 +
 
 +
{{tooltip|{{key|Shift &nbsp; &nbsp;}}|SHIFT}}
 +
{{tooltip|{{key|Z}}|Z}}
 +
{{tooltip|{{key|X}}|X}}
 +
{{tooltip|{{key|C}}|C}}
 +
{{tooltip|{{key|V}}|V}}
 +
{{tooltip|{{key|B}}|B}}
 +
{{tooltip|{{key|N}}|N}}
 +
{{tooltip|{{key|M}}|M}}
 +
{{tooltip|{{key|, &nbsp;}}|,}}
 +
{{tooltip|{{key|. &nbsp;}}|.}}
 +
{{tooltip|{{key|/ &nbsp;}}|/}}
 +
{{tooltip|{{key|Shift &nbsp; &nbsp; &nbsp; &nbsp;}}|RSHIFT}}
 +
 
 +
{{tooltip|{{key|Ctrl &nbsp;}}|CTRL}}
 +
{{tooltip|{{key|⊞}}|LWIN}}
 +
{{tooltip|{{key|Alt}}|ALT}}
 +
{{tooltip|{{key|&nbsp; &nbsp; &nbsp; Spacebar &nbsp; &nbsp; &nbsp;}}|SPACE}}
 +
{{tooltip|{{key|⊞}}|RWIN}}
 +
{{tooltip|{{key|Alt}}|RALT}}
 +
{{tooltip|{{key|Menu}}|Cannot be bound}}
 +
{{tooltip|{{key|Ctrl &nbsp; &nbsp;}}|RCTRL}}
 +
 
 +
|<!-- Spacing -->
 +
|
 +
{{tooltip|{{key|PrtScn}}|Cannot be bound}}
 +
{{tooltip|{{key|ScrLk}}|SCROLLLOCK}}
 +
{{tooltip|{{key|Pause}}|PAUSE}}
 +
 
 +
{{tooltip|{{key|Insert &nbsp;}}|INS}}
 +
{{tooltip|{{key|Home}}|HOME}}
 +
{{tooltip|{{key|PgUp}}|PGUP}}
 +
 
 +
{{tooltip|{{key|Delete}}|DEL}}
 +
{{tooltip|{{key|&nbsp; End &nbsp;}}|END}}
 +
{{tooltip|{{key|PgDn}}|PGDN}}
 +
 
 +
 
 +
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{tooltip|{{key|&uarr;}}|UPARROW}}
  
===How do plus(+) and minus(-) aliases work?===
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{tooltip|{{key|&larr;}}|LEFTARROW}}
As with plus and minus commands, plus and minus aliases are two-state aliases.  The plus state is executed (and continues to execute) while the key is pressed.  The minus state executes when the key is released.  For example, let's take a look at this plus/minus alias for an Engineer (swiped from Patty on the TF2 boards):
+
{{tooltip|{{key|&darr;}}|DOWNARROW}}
<pre>
+
{{tooltip|{{key|&rarr;}}|RIGHTARROW}}
alias "+upgradeBuilding" "slot3; +attack"
+
|<!-- Spacing -->
alias "-upgradeBuilding" "-attack; wait; slot1"
+
|
bind "mouse3" "+upgradeBuilding"
 
</pre>
 
:*'''+upgradeBuilding''' switches to the wrench and begins to swing it
 
:*'''-upgradeBuilding''' stops swinging the wrench, waits a moment, then switches back to the shotgun
 
:*Then we bind the middle mouse button to the plus-state of the alias we just created.  As long as the button is held down, the wrench will continue to swing.  As soon as the button is released, the minus-state will be executed.
 
Note that, even though the minus state is never explicitly mentioned in the keybind, the minus-state is executed upon release of the button.  This is an automatic function of plus/minus aliases.
 
{{Cleanup}}
 
  
===How are cyclical or complex aliases written?===
+
{{Scripting Numpad}}
Cyclical or complex aliases are aliases that reference or even create other aliases.  Since it's difficult to explain on a general level, let's take a look at an example:
+
|}
<pre>
 
alias "duckToggle" "duck1"
 
alias "duck1" "+duck; alias duckToggle duck2"
 
alias "duck2" "-duck; alias duckToggle duck1"
 
</pre>
 
:*First, we create an alias called '''duckToggle''' and assign it to another alias called '''duck1'''.
 
:*Second, we create the '''duck1''' alias, which begins and continues the '''duck''' command.  Then it reassigns '''duckToggle''' to a third alias called '''duck2'''.
 
:*Third, we create the '''duck2''' alias, which ends the '''duck''' command (i.e. causes the player to stand up).  Then it reassigns '''duckToggle''' back to '''duck1'''.
 
Now, the first time we execute the '''duckToggle''' alias, it will perform the '''duck1''' alias.  But the next time we execute '''duckToggle''', it will perform the '''duck2''' alias.  Now all that's left to do is to bind a key to the '''duckToggle''' alias:
 
<pre>bind "c" "duckToggle"</pre>
 
The next time we press the '''c''' key, the player will crouch.  When we press '''c''' again, the player will stand up.
 
  
===Key Combinations===
+
{|
I've used the word key combinations by lack of another word. What it actually does is this: by pressing a key, you temporary bind one or more keys to a different command then default. This makes it look just like you are using a key combination. An exemple to change class:
+
! align="left"| Mouse Button
<pre>
+
! Name of Keybind
// Quick Class Joiner Script. It has been tested and works.
+
|-
//Press shift and a key from 1-9 to change class.
+
| Scroll Up
//
+
| MWHEELUP
alias +joinclass "bind 1 scout; bind 2 soldier; bind 3 pyro; bind 4 demoman; bind 5 heavy; bind 6 engineer; bind 7 medic; bind 8 sniper; bind 9 spy"
+
|-
alias "-joinclass" "bind 1 slot1; bind 2 slot2; bind 3 slot3; bind 4 slot4; bind 5 slot5; bind 6 slot6; bind 7 slot7; bind 8 slot8; bind 9 slot9"
+
| Scroll Down
//
+
| MWHEELDOWN
alias scout "join_class scout"
+
|-
alias soldier "join_class soldier"
+
| Left Click
alias pyro "join_class pyro"
+
| MOUSE1
alias demoman "join_class demoman"
+
|-
alias heavy "join_class heavyweapons"
+
| Right Click
alias engineer "join_class engineer"
+
| MOUSE2
alias medic "join_class medic"
+
|-
alias sniper "join_class sniper"
+
| Wheel Click
alias spy "join_class spy"
+
| MOUSE3
//
+
|-
bind "shift" "+joinclass"
+
| Left Button Click (forward)
</pre>
+
| MOUSE4
By CupOfTea
+
|-
 +
| Right Button Click (back)
 +
| MOUSE5
 +
|}
  
==Additional Scripting Tips==
+
== Useful commands ==
===Why shouldn't I bind keys within aliases?===
+
{{Main|vdc:List of TF2 console commands and variables|l1=List of TF2 console commands and variables}}
There are several reasons why you generally shouldn't bind keys inside of aliases.
 
# It makes it difficult for the user to find and change those keybinds.
 
# If you have several keybinds within the alias and the user wants to change keys, missing one of the binds could break the alias.
 
# It makes that alias specific to only that key, and prevents the user from binding multiple keys to a single alias.
 
Let's look at the '''duckToggle''' alias as an example.  If we were to bind keys within that alias, it might look like this:
 
<pre>
 
//This is an example of how NOT to write an alias!
 
alias "duck1" "+duck; bind c duck2"
 
alias "duck2" "-duck; bind c duck1"
 
bind "c" "duck1"
 
</pre>
 
As you can see, when the alias is written this way, the '''c''' key is bound ''three times!''  In order for users to change that key, they must find every place where the '''c''' key has been bound.  If they miss even one instance, that alias will break.  Now let's replace those binds with alias reassignments:
 
<pre>
 
//This is a much better approach
 
alias "duckToggle" "duck1"
 
alias "duck1" "+duck; alias duckToggle duck2"
 
alias "duck2" "-duck; alias duckToggle duck1"
 
  
bind "c" "duckToggle"
+
===Disguising===
</pre>
+
The <code>disguise</code> command takes two arguments, the first being the class and the second being the team.
Now why is this better?  Well, first, the user only needs to look in one place for the keybind, so it's much easier to change. But it also allows the user to bind multiple keys or buttons without changing the alias at all!
+
:'''Class'''
<pre>
+
:1. Scout
bind "c" "duckToggle"
+
:2. Sniper
bind "v" "duckToggle"
+
:3. Soldier
bind "b" "duckToggle"
+
:4. Demoman
bind "MOUSE3" "duckToggle"
+
:5. Medic
//And so on, and on, and on
+
:6. Heavy
</pre>
+
:7. Pyro
If we were binding our keys inside our aliases, then we'd have to write the aliases multiple times: once for each key we want to bind.  But when we move the keybinding outside the aliases, we only have to write the alias once and can bind as many keys as we want to it.
+
:8. Spy
 +
:9. Engineer
  
When you're writing scripts for everyone to use, try to keep this principle in mind. Not only is it easier for users to customize, but it's also easier for you to write and maintain.
+
:'''Team'''
 +
:1. BLU team
 +
:2. RED team
 +
:-1. Opposite team
 +
:-2. Same team
  
===How to display text onscreen===
+
Thus, <code>disguise 5 1</code> would disguise as a BLU Medic and <code>disguise 7 -2</code> would disguise as a friendly Pyro.
First is the example of how, followed by the explanation.
+
:''Note:'' <code>disguise 8 -2</code> (Friendly Spy) will cause the player to un-disguise.
 +
:''Note:'' Any collection of characters and/or numbers after the class number that are not 1, 2, -1, or -2 will default the disguise to RED team, regardless of the player's current team. For example, <code>disguise 1 3</code> will disguise the Spy as a RED Scout.
  
You will need a file called ''con_filter_text_clear.cfg'' that contains:
+
=== Buildings ===
  con_filter_text ""
+
The <code>build</code> and <code>destroy</code> commands each take two arguments, the first being the building and the second being the building type. The second argument is only required if it is not <code>0</code>, and is currently only used to differentiate between teleporter entrances and exits.
  
Then in your ''autoexec.cfg''
+
The <code>build</code> command will pull up the blueprint to place a building, with an exception of the Sapper, which is wielded.
// aliases to execute the 2 scripts we made
+
:<code>build 0 0</code> will build a [[Dispenser]] <small>(Engineer only)</small>
alias "cft_clear" "exec con_filter_text_clear.cfg"
+
:<code>build 1 0</code> will build a [[teleporter entrance]] <small>(Engineer only)</small>
alias "cft_script" "con_filter_text |}"
+
:<code>build 1 1</code> will build a [[teleporter exit]] <small>(Engineer only)</small>
// aliases to toggle console filtering
+
:<code>build 2 0</code> will build a [[Sentry Gun]] <small>(Engineer only)</small>
alias "cf1" "con_filter_enable 1"
+
:<code>build 3 0</code> will build a [[Sapper]] <small>(Spy only)</small>
alias "cf0" "con_filter_enable 0"
 
// to echo a newline
 
alias "cfnl" "cf0;echo;cf1"
 
 
// if you turn this off all text disapears!  it is left always on
 
developer 1
 
// start with filtering enabled so we don't see all the console garbage on our screen
 
cf1
 
 
// you can play with the following settings
 
con_notifytime 8 // How long to display recent console text to the upper part of the game window
 
con_nprint_bgalpha 50 // Con_NPrint background alpha.
 
con_nprint_bgborder 5 // Con_NPrint border size.
 
contimes 8 // Number of console lines to overlay for debugging.
 
 
// our simple screen print test... which you can expand to do menus or whatever
 
echo "|} Isn't ofb's screen printing cool?"
 
cfnl
 
  
Okay, that's it!  Remember that when building menus you can use the ''clear'' console command to clear away your menu after it's done so it doesn't stay on the screen!  Please don't clutter people's screen with "my script loaded v1.2.3 by alphaguy", we don't need spam, TF2 is pretty; leave it that way.
+
Similarly, the <code>destroy</code> command will destroy buildings.
 +
:<code>destroy 0 0</code> will destroy a Dispenser <small>(Engineer only)</small>
 +
:<code>destroy 1 0</code> will destroy a teleporter entrance <small>(Engineer only)</small>
 +
:<code>destroy 1 1</code> will destroy a teleporter exit <small>(Engineer only)</small>
 +
:<code>destroy 2 0</code> will destroy a Sentry Gun <small>(Engineer only)</small>
 +
:''Note:'' Sappers cannot be destroyed.
  
To understand how it works, we set up a .cfg because you can't nest quotes in an alias, alias "myalias" "echo "hi okay?"" for example doesn't work. If you've found a way to escape them properly, just edit this article and update it!  We set developer to 1 which spams our users a lot, and they wouldn't know when to look for the menu, so we turn on console filtering which only prints messages that contain |}, we want something unique that wont' come up often but that doesn't look like ass on the screen because we'll always need to put it there.
+
It is possible to use the old <code>build</code> commands, which used only one argument.
 +
:<code>build 0</code> will build a Dispenser <small>(Engineer only)</small>
 +
:<code>build 1</code> will build a teleporter entrance <small>(Engineer only)</small>
 +
:<code>build 2</code> will build a Sentry Gun <small>(Engineer only)</small>
 +
:<code>build 3</code> will build a teleporter exit <small>(Engineer only)</small>
 +
:<code>build 3</code> will build a Sapper <small>(Spy only) [deprecated]</small>
  
Then when we used ''cfnl'' to echo a newline after our filtered text.  This is because filtered echo's don't add a newline, and if we didn't all our later echos would just put all the text on the same line.  Give it a try to see what I mean.  So we turn filtering off, echo a newline, then turn it back on so we don't spam our users.
+
=== Voice Menu ===
 +
The <code>voicemenu</code> command takes two arguments, the menu number and the command number.  
 +
*<code>voicemenu 0</code>
 +
*:0: {{botignore|MEDIC!}}
 +
*:1: Thanks!
 +
*:2: Go! Go! Go!
 +
*:3: Move Up!
 +
*:4: Go Left
 +
*:5: Go Right
 +
*:6: Yes
 +
*:7: No
 +
*:8: Pass To Me!
 +
*<code>voicemenu 1</code>
 +
*:0: Incoming
 +
*:1: Spy!
 +
*:2: Sentry Ahead!
 +
*:3: Teleporter Here
 +
*:4: Dispenser Here
 +
*:5: Sentry Here
 +
*:6: Activate Charge!
 +
*:7: {{botignore|MEDIC: ÜberCharge Ready}}
 +
*:8: Pass To Me!
 +
*<code>voicemenu 2</code>
 +
*:0: Help!
 +
*:1: Battle Cry
 +
*:2: Cheers
 +
*:3: Jeers
 +
*:4: Positive
 +
*:5: Negative
 +
*:6: Nice Shot
 +
*:7: Good Job
  
'''Warning: console filtering means that you will not get any console text that isn't from your scripts!  To see console output again just type ''cft_clear''.'''
+
:''Note'': If you wish to display the voicemenu, rather than fire the <code>voicemenu <num> <num></code> message, the command is <code>voice_menu_<num></code>: where <num> is a number between 1 and 3, and takes no arguments. For instance, to display the first voicemenu, one would run the command <code>voice_menu_1</code>.
  
==Console Commands==
+
=== Eureka Teleport ===
A note on syntax... if an item is surrounded in square brackets ([ or ]) it is optional; if an item is enclosed in angle brackets (< or >) then it is required for that command to work. 
+
The <code>eureka_teleport</code> can teleport an Engineer holding the [[Eureka Effect]] to their spawn or teleporter exit.
 +
*<code>eureka_teleport 0</code> will teleport the player to their spawn
 +
*<code>eureka_teleport 1</code> will teleport the player to their [[teleporter exit]]
  
===ALIAS===
+
The player will see "Unknown command" in their [[console]] even though the command works.
*Class Restrictions
 
*:None
 
*Description
 
*:Alias is simply a means of reducing a long list of commands into a small package.  For instance, take that example from the 'wait' command. If that were aliased, you could simply use that alias rather than try to remember the whole thing.  Much easier.  Plus it makes it easier to make things like communications scripts and such.
 
*Syntax
 
*:alias "<name_of_alias>" "<command; list>"
 
*Arguments
 
**None
 
  
 +
=== Assorted ===
 +
*<code>clear</code> will clear the console of any information.
 +
*<code>alias</code> will list all currently defined aliases.
 +
*<code>fov_desired (20-90)</code> will set the [[field of view]].
 +
*<code>viewmodel_fov </code> will set the FOV for weapon models. It ranges by default from 54 to 70.
 +
*<code>r_drawviewmodel (0/1)</code> will show (1) or hide (0) weapon models.
 +
*<code>lastdisguise</code> will cause the player to re-disguise as their last disguise. <small>(Spy only)</small>
 +
*<code>load_itempreset (0-3)</code> will load a particular loadout preset [A, B, C, D].
 +
*<code>say message</code> will send a message to public chat.
 +
*<code>say_team message</code> will send a message to team chat.
 +
*<code>say_party message</code> will send a message to party chat.
 +
*<code>+taunt</code> will open the player's taunt loadout.
 +
*<code>+use_action_slot_item</code> will cause the player to use their action slot item.
 +
*<code>volume (0-1)</code> will change the in-game volume.
 +
*<code>taunt_by_name (name)</code> will run a specified taunt, given the exact name of a taunt in the player's current taunt loadout, without opening the taunt menu.
 +
*<code>key_findbinding (string)</code> will list all keys bound to a string containing the given substring (case-sensitive).
 +
*<code>key_listboundkeys</code> will list all keys currently bound and their associated commands.
  
 +
== Advanced Scripting Techniques ==
 +
=== Toggles ===
 +
It is possible to bind a key to toggle a command which would otherwise be a press and hold command.
  
===BUILD===
+
<pre>bind w toggle_movement
*Class Restrictions
+
alias toggle_movement enable_movement
*:Engineer, Spy
+
alias enable_movement "alias toggle_movement disable_movement;+forward"
*Description
+
alias disable_movement "alias toggle_movement enable_movement;-forward"</pre>
*:If the Engineer who used this command has enough metal, it will put him into build mode for the item specified.  If a Spy uses this command, he will arm the Electro sapper, ready to use on any hostile gadgets targeted.
+
This script will cause a press of {{key|W}} to keep the player moving forward until {{key|W}} is pressed again.
*Old syntax
 
*:build <gadget_number>
 
*Old arguments
 
**<gadget_number>
 
**:0: [[Dispenser]] (Engineer)
 
**:1: [[Teleporter]] entrance (Engineer)
 
**:2: Teleporter exit (Engineer)
 
**:3: [[Sentry gun]] (Engineer)
 
**:4: [[Electro sapper]] (Spy)
 
*New syntax
 
*:build <group_number> <gadget_number>
 
*New arguments
 
**<group_number>
 
**:0: [[Dispenser]] (only Engineer)
 
**:1: [[Teleporter]] (only Engineer)
 
**:2: [[Sentry gun]] (only Engineer)
 
**:3: [[Electro sapper]] (only Spy)
 
**<gadget_number>
 
**:0: for sentry, dispenser, teleporter entry or electro sapper
 
**:1: for teleporter exit
 
*Example
 
*:> build 2 0 (build a sentry)
 
*:> build 1 1 (build a tele exit)
 
  
''NOTE: Currently you cannot call build a second time with an Engineer when you are already in build mode, you need to swap to any of your weapon before being able to call build again (bug or feature?)''
+
=== Key combinations ===
 +
It is possible to create a script where holding down a key changes the action of another key. For example, the following script can be used to make {{key|Alt}}+{{key|F4}} exit the game:
  
''NOTE: This issue is fixed, the build command can now be called repeately without problems.''
+
<pre>
 +
alias +alt_pressed  bind f4 exit
 +
alias -alt_pressed unbind f4
  
''NOTE: After the 01 may 2010 update, old syntax still works the same.
+
bind alt +alt_pressed
 +
</pre>
 +
Note that pressing Alt will execute <code>+alt_pressed</code>, and releasing it will execute <code>-alt_pressed</code>.
  
===DESTROY===
+
=== Wait-testing ===
*Class Restrictions
+
Since the <code>wait</code> command is integral to some scripts, it may be necessary to test to see if a server has disabled the command.
*:Engineer, Spy
 
*Description
 
*:If you have built the gadget represented by the number, congratulations, you are the prowd owner of newly minted scrap metal. Useful for Engineers who want to relocate their buildings, but largely useless for Spies (who would be very unlikely to actually want to destroy their own sappers).
 
*Old syntax
 
*:destroy <gadget_number>
 
*Old arguments
 
**<gadget_number>
 
**:0: Dispenser (Engineer)
 
**:1: Teleport Entrance (Engineer)
 
**:2: Teleport Exit (Engineer)
 
**:3: Sentry (Engineer)
 
**:4: Electro Sapper (Spy)
 
*New syntax
 
*:destroy <group_number> <gadget_number>
 
*New arguments
 
**<group_number>
 
**:0: [[Dispenser]] (only Engineer)
 
**:1: [[Teleporter]] (only Engineer)
 
**:2: [[Sentry gun]] (only Engineer)
 
**<gadget_number>
 
**:0: for sentry, dispenser or teleporter entry
 
**:1: for teleporter exit
 
*Example
 
*:> destroy 2 0 (destroy sentry)
 
*:> destroy 1 1 (destroy tele exit)
 
  
===DISGUISE===
+
<pre>alias waitTester "alias waitTest waitPositive; wait 0; waitTest"
*Class Restrictions
+
alias wait "alias waitTest waitNegative"
*:Spy
+
alias waitPositive "echo Wait is enabled on this server.; exec waitPositive.cfg"
*Description
+
alias waitNegative "echo Wait is DISABLED on this server!; exec waitNegative.cfg"
*:This, as is fairly easy to tell from the command itself, will disguise you as someone.  Who, however, depends on the numbers.  The first number represents the class you wish to be, while the second represents the team. When I was testing this out, team numbers above two still worked, so I imagine that it's forward-thinking support in case someone wants to remake a murderball map or something. Also, using negative numers allows you to disguise as either your team or the enemy team without setting up a team loader.
+
waitTester</pre>
*Syntax
+
This script relies on the fact that if the wait command is disabled on a server, the alias named <code>wait</code> can be defined by the user. Thus, the script creates an alias named <code>waitTest</code> which by default points to <code>waitPositive</code>, but if <code>wait</code> is not allowed (and can thus be defined by the user), will be redirected to <code>waitNegative</code>.
*:disguise <class_number> <team_number>
 
*Arguments
 
**<class_number>
 
**:1: Scout
 
**:2: Sniper
 
**:3: Soldier
 
**:4: Demoman
 
**:5: Medic
 
**:6: Heavy Weapons Guy
 
**:7: Pyro
 
**:8: Spy
 
**:9: Engineer
 
**<team_number>
 
**:1: Blu
 
**:2: Red
 
**:-1: The Enemy Team
 
**:-2: My Team
 
  
===LASTDISGUISE===
+
=== Loops ===
*Class Restrictions
+
:'''Warning: Loops which run without a wait command will cause the TF2 client to hang. It is highly suggested to run a looping script only after a wait testing script.'''
*:Spy
+
It is generally considered bad form to have one alias point to itself, as although the loop can be broken out of, it cannot be reset. Therefore, looping scripts tend to include two parts to the loop: The part that waits, and the part that loops.
*Description
 
*:As one might imagine, this command changes your disguise to the last one you had. It will remember disguises after a death. This is bound to 'b' by default.  Lastdisguise random will chooses a random disguise that's neither Spy nor Scout. Using the command whilst already disguised as your last disguise will switch the weapon of the disguise to the corresponding weapon armed.
 
*Syntax
 
*:lastdisguise [random]
 
*Arguments
 
**[random]
 
**:Chooses a random disguise that's neither Spy nor Scout
 
  
===LASTINV===
+
<pre>bind g loopKey
*Class Restrictions
+
alias loopKey startLoop
*:None
+
alias startLoop "alias loopKey stopLoop;+attack;alias redirect loop;loop"
*Description
+
alias stopLoop "-attack;alias redirect;alias loopKey startLoop"
*:This one's real easy.  All it does is switch you back to your previously used weapon.  (And I'm sure some of you probably realize that this is exactly the command that 'q' is bound to by default.)
+
alias loop "+left;wait 33;-left;+right;wait 33;-right;redirect"</pre>
*Syntax
 
*:lastinv
 
*Arguments
 
**None
 
  
 +
This script will start looping once {{Key|G}} is pressed. It begins by firing, and then switches the player's view back and forth every 33 frames (half of a second on most servers). Pressing {{Key|G}} would cause the next iteration of the loop to stop, also stopping the firing.
  
 +
=== Sequences ===
 +
<pre>alias +pyrocombo "slot1;+attack;wait 32;slot2"
 +
alias -pyrocombo "-attack;slot1"</pre>
 +
This script will create two aliases, one to start a sequence, and one to end it. The sequence will switch to a Pyro's [[Degreaser]] and fire for 32 ticks, before switching to the [[Panic Attack]] and shooting until the button is no longer held. Sequences can also be made like this:
 +
<br><pre>alias quickscope "slot1;+attack2;wait 32;+attack;wait 16;-attack;-attack2"</pre>
 +
This script will create a sequence alias, that once activated will cause the Sniper to quick-scope his [[Sniper Rifle]]; by executing the long string of commands called a sequence.
 +
Sequences are useful in making scripts, and learning how to make one will help in the long run of scripting.
  
===MENUSELECT===
+
=== Cycles ===
*Class Restrictions
+
A cycle is toggle script where there are a minimum of 3 possible options, which loop (ex, 1, 2, 3, 1). Example:
*:None
+
<pre>
*Description
+
alias message_1 "say message 1.; bind x message_2"
*:Menuselect does ONLY the menu portion of slotX, so refer to that entry for the detailed explanation.  Also, it ONLY works on VGUI menus, such as the voice command menus, not the visual menus like those that are used to choose class, or select which building to construct as an Engineer, etc.
+
alias message_2 "say message 2.; bind x message_3"
*Syntax
+
alias message_3 "say message 3.; bind x message_1"
*:menuselect <item_number>
+
bind x message_1
*Arguments
+
</pre>
**<item_number>
+
This script makes it so pressing the {{Key|X}} key will cycle between making you say "message 1", "message 2", and "message 3".
**:Any valid menu choice.
 
*Note:  Use '''cancelselect''' to leave a menu.
 
  
  
 +
{{note|<code>[[vdc:toggle|toggle]]</code>, <code>[[vdc:incrementvar|incrementvar]]</code>, and <code>[[vdc:multvar|multvar]]</code> can often be used in place of aliases when a console variable is being changed.}}
  
 +
=== Selection addons ===
 +
A selection script is built onto a cycle to make it more intuitive. Selection scripts allow cycling upwards and downwards, ultimately giving more control for selecting which command(s) to run.
 +
<pre>
 +
alias CondC_UP Cond1
 +
alias CondC_DOWN Cond5
 +
alias ApplyCond ApplyCond33
 +
alias ApplyCond33 "addcond 33"
 +
alias ApplyCond49 "addcond 49"
 +
alias ApplyCond72 "addcond 72"
 +
alias ApplyCond74 "addcond 74"
 +
alias ApplyCond90 "addcond 90"
 +
alias Cond1 "alias CondC_UP Cond2;alias CondC_DOWN Cond5;alias ApplyCond ApplyCond33"
 +
alias Cond2 "alias CondC_UP Cond3;alias CondC_DOWN Cond1;alias ApplyCond ApplyCond49"
 +
alias Cond3 "alias CondC_UP Cond4;alias CondC_DOWN Cond2;alias ApplyCond ApplyCond72"
 +
alias Cond4 "alias CondC_UP Cond5;alias CondC_DOWN Cond3;alias ApplyCond ApplyCond74"
 +
alias Cond5 "alias CondC_UP Cond1;alias CondC_DOWN Cond4;alias ApplyCond ApplyCond90"
 +
</pre>
 +
This gives more control in what conditions to add to the player. This also allows for better freedom of selection and ease of use, as it makes scrolling through options in the cycle possible.
  
===PLAY===
+
=== Randomization ===
*Class Restrictions
+
Randomization is a strange and niche feature. Randomization is rarely used, as most processes aren't as useful when randomized. However, randomization can be useful for chat binds, such as for trade advertising.
*:None
 
*Description
 
*:Plays a selected .wav file locally (which is to say, only the user will hear it through their client). To find a .wav file to play, you will need to have a GCF explorer such as GCFScape [http://developer.valvesoftware.com/wiki/GCFScape]. With this you can find the path and the sound file you wish to play, and reference it via the console (or scripting).
 
:You can also add your own .wav files to '''C:\Program Files\Steam\steamapps\USERNAME\team fortress 2\tf\sound\'''. (See '''Custom .wav files''' below.)
 
*Syntax
 
*:play <path><sound_file_name.wav>
 
*Example
 
*:play vo/demoman_specialcompleted11.wav
 
*Arguments
 
**None
 
  
====Custom .wav files====
+
'''Note: Due to the nature of TF2's scripting, this section will be considerably long. If you don't already have an understanding of how cycles work, the information presented may not be relevant.'''
Adding your own .wav files is as simple as dropping them in your '''C:\Program Files\Steam\steamapps\USERNAME\team fortress 2\tf\sound\''' folder.  This folder represents the root of the .wav file's path. For example, if you drop a single .wav file called '''soldier.wav''' into that folder, then you can play it by using the following command:
 
 
<pre>
 
<pre>
play soldier.wav
+
alias call f1
 +
alias cycle c2
 +
 
 +
alias c1 "alias cycle c2;alias call f1"
 +
alias c2 "alias cycle c3;alias call f2"
 +
alias c3 "alias cycle c4;alias call f3"
 +
alias c4 "alias cycle c5;alias call f4"
 +
alias c5 "alias cycle c1;alias call f5"
 +
 
 +
alias f1 "say 1"
 +
alias f2 "say 2"
 +
alias f3 "say 3"
 +
alias f4 "say 4"
 +
alias f5 "say 5"
 +
 
 +
alias +w "+forward;cycle"
 +
alias -w "-forward;cycle"
 +
alias +a "+moveleft;cycle"
 +
alias -a "-moveleft;cycle"
 +
alias +s "+back;cycle"
 +
alias -s "-back;cycle"
 +
alias +d "+moveright;cycle"
 +
alias -d "-moveright;cycle"
 +
 
 +
bind o call
 +
bind w +w
 +
bind a +a
 +
bind s +s
 +
bind d +d
 
</pre>
 
</pre>
If you drop a .wav file into a subdirectory of that folder, then you need to preface the filename with the name of that subdirectory. For example, if you drop '''Soldier.wav''' into '''C:\Program Files\Steam\steamapps\USERNAME\team fortress 2\tf\sound\classes\''' then you can play it using the following command:
+
This script is assigning and resigning multiple alias values. When any of the {{key|WASD}} keys are pressed or released, the cycle command is ran, which moves the cycle command to the next value in the cycle and sets the "call" command to a value corresponding to the cycle number. This is based on the player's movement, and only changes values if the player is moving. It is possible to make this randomizer more effective by using other various techniques stated here (ex. Loops), but this example is for demonstration purposes only.
 +
 
 +
=== Timed action ===
 +
Timed or held actions trigger when a button is pressed down for a certain amount of time. Timed actions can be used in situations where a script or command shouldn't be instantly ran the moment a button is pressed (ex. accidentally pressing a disconnect bind).
 +
 
 
<pre>
 
<pre>
classes/soldier.wav
+
alias "+ti_zoom" "alias zoom_con zoomOn; wait 132; zoom_con"
 +
alias "-ti_zoom" "zoomOff; alias zoom_con ; rb_tizoom-M4"
 +
alias "rb_tizoom-M4" "unbind mouse4; wait 132; bind mouse4 +ti_zoom"
 +
alias "zoomOn" "fov_desired 20; r_drawviewmodel 0"
 +
alias "zoomOff" "fov_desired 90; r_drawviewmodel 1"
 +
bind "mouse4" "+ti_zoom"
 
</pre>
 
</pre>
  
===SLOT<X>===
+
Pressing (and immediately releasing) {{key|Mouse 4}} with this script loaded will have no noticeable effect, however holding down {{key|Mouse 4}} for 2 seconds will cause the script to lower the FOV to 20, and hide viewmodels. Letting go of {{key|Mouse 4}} at any point will undo these changes by setting the FOV to 90 and unhiding viewmodels.
*Class Restrictions
 
*:None
 
*Description
 
*:This command has a little more depth to it than first appears.  While it is mainly used to choose a weapon, it can also be used as feedback to the default voice menus at 'z', 'x', and 'c'.  For instance, if you have 'f' bound to 'slot1' and activate voice_menu_1 ('z'), pressing 'f' would cause you to call for a Medic.  With regard to choosing a weapon, this command can act one of two ways.  If you have fast weapon switching turned on, this command will immediately switch to that weapon.  If you do not, this command will only highlight whatever weapon slot it represents and it remains up to you to do the final selection.  Or you can use this to do it for you: "slot1; wait 50; +attack; wait; -attack".
 
*Syntax
 
*:slot<slot_number>
 
*Arguments
 
**<slot_number>
 
**:Needs to be a number between 0 and 10.  '''slot10''' exits a menu.
 
  
 +
This works because of the use of + and - aliases. Pressing the key <code>+ti_zoom</code> is bound to will redefine <code>zoom_con</code> to activate the script, and if left pressed for the <code>wait</code> duration will execute the script. However, if the button is released, <code>zoom_con</code> is redefined to do nothing. The key is then "disabled" by being unbound for the same <code>wait</code> duration, and rebound afterwards to restore use of the key.
  
 +
'''Note:''' Rebinding of the key is technically redundant, as the script will not execute the timed action if the button is released. However, if the button is pressed multiple times it is possible to execute the timed action if the confirmation alias (in this case, <code>zoom_con</code> is properly defined as any of the presses would execute it. Unbinding the key for the same duraiton of the original <code>wait</code> delay ensures that the effect can't be triggered if the button is rapidly pressed.
  
===USE===
+
=== Basic Conditionals ===
*Class Restrictions
+
{{rewrite}}
*:None
+
The basic conditional allows a script to change its behavior without running an entirely new script. By making use of a dummy alias it is possible to change the outcome of an input based on other inputs. Basic conditionals can support potentially infinitely many checks on the state of other commands, however it's unlikely that a script would need more than a few checks per conditional.
*Description
 
*:The "use" command is used to literally use the specified weapon. No muss, no fuss, you just pull out that weapon if you have it.
 
*Syntax
 
*:use <weapon_name>
 
*Arguments
 
**<weapon_name>
 
***Scout
 
**:tf_weapon_scattergun
 
**:tf_weapon_pistol_scout
 
**:tf_weapon_lunchbox_drink
 
**:tf_weapon_bat
 
**:tf_weapon_bat_wood
 
***Soldier
 
**:tf_weapon_rocketlauncher
 
**:tf_weapon_rocketlauncher_directhit
 
**:tf_weapon_shotgun_soldier
 
**:tf_weapon_buff_item
 
**:tf_weapon_shovel
 
**:tf_weapon_sword
 
***Pyro
 
**:tf_weapon_flamethrower
 
**:tf_weapon_shotgun_pyro
 
**:tf_weapon_flaregun
 
**:tf_weapon_fireaxe
 
***Demoman
 
**:tf_weapon_grenadelauncher
 
**:tf_weapon_grenade_demoman
 
**:tf_weapon_pipebomblauncher
 
**:tf_weapon_pumpkin_bomb
 
**:tf_weapon_bottle
 
**:tf_weapon_base
 
**:tf_weapon_sword
 
***Heavy Weapons Guy
 
**:tf_weapon_minigun
 
**:tf_weapon_shotgun_hwg
 
**:tf_weapon_lunchbox
 
**:tf_weapon_fists
 
***Engineer
 
**:tf_weapon_shotgun_primary
 
**:tf_weapon_sentry_revenge
 
**:tf_weapon_pistol
 
**:tf_weapon_laser_pointer
 
**:tf_weapon_wrench
 
**:tf_weapon_robot_arm
 
**:tf_weapon_pda_engineer_destroy
 
**:tf_weapon_pda_engineer_build
 
***Medic
 
**:tf_weapon_syringegun_medic
 
**:tf_weapon_medigun
 
**:tf_weapon_bonesaw
 
***Sniper
 
**:tf_weapon_sniperrifle
 
**:tf_weapon_compound_bow
 
**:tf_weapon_smg
 
**:tf_weapon_jar
 
**:tf_weapon_club
 
***Spy
 
**:tf_weapon_revolver
 
**:tf_weapon_knife
 
**:tf_weapon_pda_spy
 
**:''see the [[Scripting#BUILD|Build]] section for how to equip sapper''
 
  
===VOICEMENU===
+
A very basic example of a conditional may look like:
*Class Restrictions
+
<pre>
*:None
+
alias "check_test" "alias test success; check1; check2; test"
*Description
+
alias "check1" ""
*:This command is basically a direct method of using the 'z', 'x', and 'c' keys to send voice messages.  Basically this allows you to bind a voice message directly to a key in the same fashion as how 'e' is by default bound to call in a Medic.
+
alias "check2" ""
*Syntax
+
alias "test" "success"
*:voicemenu <menu_number> <phrase_number>
 
*Arguments
 
**<menu_number>
 
***0 <phrase_number>
 
***:0: Medic
 
***:1: Thanks
 
***:2: Go
 
***:3: Move Up
 
***:4: Flank Left
 
***:5: Flank Right
 
***:6: Yes
 
***:7: No
 
***1 <phrase_number>
 
***:0: Incoming
 
***:1: Cloaked Spy
 
***:2: Sentry Ahead
 
***:3: Teleporter Here
 
***:4: Dispenser Here
 
***:5: Sentry Here
 
***:6: Activate Ubercharge
 
***:7: (Medic Only) Ubercharge Ready
 
***2 <phrase_number>
 
***:0: Help
 
***:1: Battlecry
 
***:2: Cheers
 
***:3: Jeers
 
***:4: Positive
 
***:5: Negative
 
***:6: Nice Shot
 
***:7: Good Job
 
  
 +
alias "fail_check" "alias test failure"
  
 +
alias "success" "echo SUCCESS!"
 +
alias "failure" "echo FAILURE!"
  
===WAIT===
+
alias "+k_pressed" "alias check1 fail_check"
*Class Restrictions
+
alias "-k_pressed" "alias check1"
*:None
+
alias "+j_pressed" "alias check2 fail_check"
*Description
+
alias "-j_pressed" "alias check2"
*:This command is very useful when running multiple commands on the same line.  Basically, what this command does is halts the execution of that line for X frames based on its parameter.  If you don't use a parameter, it defaults to 1.  For me, a value of 100 equals roughly a second, but I haven't had time to check whether this is server or client dependant or not, so you may have to adjust your own times accordingly.  An example might be as follows for an Engineer upgrading his SG:
 
"use tf_weapon_wrench; wait; +duck; wait; +attack; wait 500; -attack; wait; -duck; lastinv"
 
What that does is switch his wrench, ducks, starts swinging the wrench and continues for 5 seconds or so, stops swinging, stands up, and switches back to the last weapon used.  If you were to attempt that without the waits, there's a pretty good chance it would fail rather spectacularly.
 
It is important to note that, unlike wait commands of the past, waits will not delay further input, and can be used simply as a timer for scripting in general.
 
*Syntax
 
*:wait [wait_time]
 
*Arguments
 
**[wait_time]
 
**:A value between 1 and <unknown>.  Default is 1.
 
*'''A Note About The Wait Command'''
 
:Valve has fixed the functionality of the sv_allow_wait_command server variable. When disabled (set to 0) the engine simply ignores and omits any wait commands that the server is given. Consequently, many scripts on this website are broken or will only function in very specific situations. This variable is set to 1 by default, but many servers base their server.cfg files off of competitive league settings, which typically disable wait commands. Furthermore, scripts that do loops (see [[Scout_scripts#Autopistol|Autopistol Script]] for an example) will crash your client when triggered.
 
  
===Other Common GoldSource/Source Scripting Commands===
+
bind "l" "check_test"
 +
bind "j" "+j_pressed"
 +
bind "k" "+k_pressed"
 +
</pre>
  
Class select '''changeclass'''
+
The main function of this script is the <code>check_test</code> alias. When ran, this alias checks the other 2 conditionals, and if the checks succeed it runs the <code>success</code> alias. However, if one of the checks fails, the dummy alias <code>test</code> is pointed to run the <code>failure</code> alias. Simply put, when a check succeeds the checking command doesn't redirect the alias <code>test</code> is pointing to. If a check fails, it redirects the <code>test</code> alias to the alias storing the code to run when the check fails.
  
Console Toggling  '''toggleconsole'''
+
In this case, pressing the button {{key|L}} without pressing either {{key|J}} or {{key|K}}, the check succeeds and prints <code>SUCCESS!</code> to the console. When pressing and holding either {{key|J}} or {{key|K}} and then pressing {{key|L}}, the check will fail and print <code>FAILURE!</code> to the console.
  
Crouch  '''+duck'''
+
A real world example of basic conditionals:
 +
<pre>
 +
// Change the crosshair color when moving around
  
Drop item '''dropitem'''
+
alias "+w_pressed" "+forward;  alias check_w pressed_w; chc_forward"
 +
alias "+a_pressed" "+moveleft; alias check_a pressed_a; chc_left"
 +
alias "+s_pressed" "+back;      alias check_s pressed_s; chc_back"
 +
alias "+d_pressed" "+moveright; alias check_d pressed_d; chc_right"
  
Echo message '''echo'''
+
alias "-w_pressed" "-forward;  alias check_w; check_none"
 +
alias "-a_pressed" "-moveleft; alias check_a; check_none"
 +
alias "-s_pressed" "-back;      alias check_s; check_none"
 +
alias "-d_pressed" "-moveright; alias check_d; check_none"
  
Fire weapon  '''+attack'''
+
alias "check_w"
 +
alias "check_a"
 +
alias "check_s"
 +
alias "check_d"
  
FPS view  '''cl_showfps 1'''
+
alias "pressed_w" "dchk_fail; chc_forward"
 +
alias "pressed_a" "dchk_fail; chc_left"
 +
alias "pressed_s" "dchk_fail; chc_back"
 +
alias "pressed_d" "dchk_fail; chc_right"
  
Handedness left  '''setinfo lefthand 1'''
+
alias "check_none" "check_s; check_a; check_d; check_w; dmy_check"
 +
alias "dmy_check" "chc_success"
  
Handedness right  '''setinfo lefthand 0'''
+
alias "dchk_fail" "alias dmy_check chc_failure"
 +
alias "dchk_reset" "alias dmy_check chc_success"
  
Jump  '''+jump'''
+
alias "chc_failure" "dchk_reset"
 +
alias "chc_success" "chc_default"
  
Last weapon  '''lastinv'''
+
alias "chc_default" "color0"
 +
alias "chc_forward" "color1"
 +
alias "chc_left"    "color2"
 +
alias "chc_back"    "color3"
 +
alias "chc_right"  "color4"
 +
 
 +
// Binds
 +
bind "w" "+w_pressed"
 +
bind "a" "+a_pressed"
 +
bind "s" "+s_pressed"
 +
bind "d" "+d_pressed"
 +
 
 +
// Colors
 +
alias "color0" "cl_crosshair_red 0; cl_crosshair_green 255; cl_crosshair_blue 0"        // Default color when not moving
 +
alias "color1" "cl_crosshair_red 0; cl_crosshair_green 0; cl_crosshair_blue 255"        // Color when moving forward
 +
alias "color2" "cl_crosshair_red 255; cl_crosshair_green 0; cl_crosshair_blue 255"      // Color when moving left
 +
alias "color3" "cl_crosshair_red 128; cl_crosshair_green 212; cl_crosshair_blue 255"    // Color when moving back
 +
alias "color4" "cl_crosshair_red 255; cl_crosshair_green 140; cl_crosshair_blue 25"    // Color when moving right
 +
</pre>
  
Logo spray  '''impulse 201'''
+
This script will change the color of the user's crosshair as they walk around with the {{key|WASD}} keys. An important note this script takes advantage of is that when a check fails it can do several things instead of just changing the dummy command for testing. When a check fails the crosshair will change colors, and also change the dummy command to fail the check. This means when several buttons are released, the crosshair's color will properly change to the most recently pressed key.
  
Look down  '''+lookdown'''
+
== Commenting ==
 +
As scripts get longer, the need for well-named aliases grows. However, it is not always sufficient to explain what an alias does simply by its name. Adding a pair of forward slashes (//) will turn the rest of the line into a comment–it will not execute any actions on the text.
  
Look up  '''+lookup'''
+
<pre>voicemenu 1 6 //Activate Charge!</pre>
 +
Since it is not obviously clear what the voice command is, a comment can explain it.
  
Map info  '''showbriefing'''
+
== Noteworthy scripts ==
 +
There are several notable scripts that have affected gameplay. Some of these are patched out, while others remain functional.
  
Map list  '''listmaps'''
+
=== Patched scripts ===
 +
==== Pistol scripts ====
 +
Originally, the [[Pistol]] could be fired almost as fast as the human hand could press a key. Scripts were created to simulate this rapid pressing by holding down a single key.
  
Move backward  '''+back'''
+
{{Patch name|8|13|2009}}: The Pistol now fires at a fixed rate, not based on the speed of pressing the fire button.
 +
==== Chargin' Targe turn scripts ====
 +
Originally, the keyboard commands to turn left and right were not treated the same as the mouse commands. The [[Chargin' Targe]] was the first weapon to create a restriction on how quickly a player could turn, therefore Valve put a limit on mouse turn-speed, yet forgot to apply the same restriction to the keyboard command that resulted in the same action. Scripts were created to rebind the turning controls when a player charged, circumventing this restriction.
  
Move forward  '''+forward'''
+
{{Patch name|6|23|2011}}: Fixed an exploit with the Chargin' Targe that allowed greater turning control than intended.
  
Netgraph  '''netgraph <num>'''
+
==== Air crouching scripts ====
 +
Originally, players could crouch as many times as they liked in a single jump. By binding a script to crouch and uncrouch as rapidly as possible, the engine could be exploited to make it difficult to properly register shots on jumping targets.
  
Next weapon  '''invnext'''
+
{{Patch name|3|6|2009}}: Players can now only duck twice in the air.
  
Playerlist  '''listplayers'''
+
==== Idling Scripts ====
 +
Most servers seek to prevent players idling for [[Item drop system|drops]]. Players can try to outsmart these systems with scripts that simulate basic movement.
  
Previous weapon  '''invprev'''
+
[http://www.teamfortress.com/post.php?id=11105 An Active Solution to an Idle Threat] requires players to accept a pop-up notification in order to continue to get drops.
  
Public message  '''say'''
+
=== Current Scripts ===
 +
==== Weapon Viewmodel Hiding Scripts ====
 +
There are a large number of scripts which toggle the weapon viewmodel depending on which weapon slot is selected for a class. Players often make their viewmodels invisible to clear up the screen, but make items like melee weapons, PDAs, watches, and so forth visible because these models indicate important information. For example, the [[Spy]] relies heavily on his viewmodel to determine when he is cloaked, when his Cloak is disturbed, and when the [[Dead Ringer]] activates. Other classes use the melee animations to judge when their attacks will hit.
  
Reload weapon '''+reload'''
+
==== Weapon Zoom Scripts ====
 +
By changing your [[FOV]], this script creates the visual effect of zooming in with whatever weapon the user is holding. It can usually be toggled between a zoomed and normal (unzoomed) version.
  
Score overview  '''+showscores'''
+
==== Sentry Jumping Scripts ====
 +
Since the [[Engineer Update]], Engineers have been able to pack up and carry their [[Sentry Gun]]s. Simultaneously introduced in the update, the [[Wrangler]] allows Engineers to [[Sentry jump]] with their Sentry rockets. With extremely fast inputs, it was discovered that a player could Sentry jump and successfully pack up their Sentry before they were launched away.
  
Screenshot  '''snapshot'''
+
While a human can repeat this feat, it is difficult. Some players made scripts which could reliably execute the commands in the right order at the right speed allowing them to make a Sentry jump while carrying their Sentry every time.
 +
:''Note:'' The [[Rescue Ranger]] can circumvent this necessity, as it can pick up [[buildings]] at range for 100 [[metal]].
  
Strafe  '''+strafe'''
+
==== Gunslinger Scripts ====
 +
Since it can be troublesome to destroy then rebuild a [[Combat Mini-Sentry]] in the heat of battle through the PDA, some players have scripted the destruction and rebuilding of their Combat Mini-Sentry with the click of one or two buttons. Such a script is especially useful when using the [[Frontier Justice]], as the player gains practically instant access to revenge crits when needed.
  
Strafe Left  '''+moveleft'''
+
==== Sensitivity and Control scripts ====
 +
Some players prefer different mouse sensitivities and control schemes for some classes. For example, changing from the Medic, which doesn't require fine aiming, to the Sniper, which encourages high precision headshots, a player may wish to change their mouse sensitivity. These scripts alter control schemes and mouse settings on a per class, or even per weapon, basis.
  
Strafe Right  '''+moveright'''
+
==== Charge Dash Scripts ====
 +
Since timing a charge and jump can be difficult, some players may use a quick script that binds the two actions to a button so that the charge dash will cover the maximum amount of distance possible. The player is still required to swing their melee weapon normally to end the charge though.
  
Secondary weapon function  '''+attack2'''
+
==== Quickscope Scripts ====
 +
Many players find it difficult to scope in and fire straight after to get a quick headshot. There are scripts that will zoom in and fire just by clicking one button. This does require players to aim outside of the scope, though.
  
Taunt '''taunt'''
+
==== Rocket Jump Scripts ====
 +
In order to [[Jumping#Soldier jumps|Rocket Jump]] to a maximum height or distance, it is required that the player jumps, crouches, and fires their rocket at roughly the same time. This can be easily scripted to occur with the press of a button.
  
Suicide '''kill'''
+
==== Auto-Disguise Scripts ====
 +
For Spies who find manually disguising to be a hassle, this script automatically disguises as a chosen class after the player attacks with any weapon. Auto-disguise can usually be toggled and customized to choose a disguise to use.
  
Suicide by Explosion '''explode'''
+
==== ÜberCharge Broadcasting Scripts ====
 +
With this script, activating ÜberCharge as [[Medic]] will also write a custom message in team chat to alert your teammates about your activation, in order to encourage your team to push ahead with you. A similar script, upon activation, plays the "ÜberCharge Ready" voice command while writing in team chat that you faked your Über to fool the enemy team.
  
Team message  '''say_team'''
+
==== Medic Radar ====
 +
This script only works for Medic, as it lets you press a button to temporarily set the autocall percentage to a very high number. This makes it so that you can see the locations of nearby teammates.
 +
Script:
 +
<pre>alias "autocall_default" "hud_medicautocallersthreshold 75.730003/Custom Threshold"
 +
alias "autocall_all" "hud_medicautocallersthreshold 150"
 +
alias "+radar" "autocall_all"
 +
alias "-radar" "autocall_default"
 +
bind [KEY] "+radar</pre>
  
Team select  '''changeteam'''
+
==== Kill-Bind Scripts ====
 +
{{main|Suicide}}
 +
In certain circumstances, such as when cornered by a Medic wielding the [[Ubersaw]], it can be beneficial for a class to be able to kill themselves quickly (in this case, to deny the Medic Über) with a key bind (for example, <code>bind k kill</code>). Although mostly only relevant in competitive play, there are occasional uses in public servers, often for comedic effect instead of to benefit gameplay. The killbind can be set to explode you if you use <code>explode</code> instead (for example, <code> bind k explode</code>). There is no difference between these two mechanically.
  
Turn left  '''+left'''
+
==== Null-Cancelling Movement Scripts ====
 +
In stock TF2, pressing two opposing movement keys at once (such as "A" (+moveleft) and "D" (+moveright)) will cancel all movement and render the player immobile, which can be a fatal mistake during battle. This script makes it so that the direction of the last key pressed will be used instead. For example, pressing "A" will make the player go left, and pressing "D" while still holding "A" will make the player go right instead of stopping.
  
Turn right  '''+right'''
+
==== Chat Bind Scripts ====
 +
Chat bind scripts are designed to post a pre-written message in the in-game text chat. Typically, users will bind these scripts to a key on their keyboard for easy repitition. These scripts can vary from user-to-user, and can say anything within the text limit, depending on what a player would want to say. Some common binds are used for team co-ordination, such as a bind to tell a team that their Medic has popped an [[ÜberCharge]]. Other common binds are used for banter, such as messages upon kills and/or dominations. Another variation on this is a trade offer bind, where it sends information to the chat about a possible trade offer. This type of script can also be automated to send these offers every couple of minutes.
  
Voice Chat  '''+voicerecord'''
+
==== Voice Toggle ====
 +
This script enables you to voice toggle, instead of push-to-talk.
 +
Script:
 +
<pre>bind [KEY] mic_toggle
 +
alias mic_toggle mic_enable
 +
alias mic_enable "+voicerecord; alias mic_toggle mic_disable"
 +
alias mic_disable "-voicerecord; alias mic_toggle mic_enable"</pre>
  
( ''"S.A.S's Guide to Counter-Strike: Scripting"'' )
+
== Notes ==
 +
* Each config file is limited to one [[w:mebibyte|mebibyte]] (1.04858 megabytes) of information, though this restriction can be circumvented by [[#Exec|exec-ing]] another config file at the end of the first.
  
==See also==
+
== See also ==
:*To share your scripts or to view scripts written by the community, please visit the [[Community Scripts]] page.
+
* [[List of useful console commands]]
 +
* {{vdc|List of TF2 console commands and variables}}
 +
* {{vdc|Command Line Options|Command Line Options}}
 +
* {{vdc|VScript}}
 +
* [[Cheats]]
  
[[Bindable keys]] - A List of the keys that are bindable and their scripting names
+
== External links ==
 +
* [https://gamebanana.com/scripts/games/297 Hundreds of scripting examples on Gamebanana]
 +
* [https://cfg.tf cfg.tf, website dedicated to Team Fortress 2 configuration]
  
{{Languages}}
+
[[Category:Customization]]
[[Category:Scripts]]
 

Revision as of 19:36, 14 April 2024

This thing ain't on auto-pilot, son!
The Engineer after using his sentry jump script

Scripting is the use of configuration files (.cfg) mainly to create new keybinds and aliases, automating complex behaviors and console command sequences. Unlike hacking, scripting is built into Team Fortress 2 and is not banned by VAC (Valve Anti-Cheat). Uses of scripting vary from simply binding a key to a command to self-referential loops and nested aliases that redefine one another. Any functionality that can be created with scripting can also be accomplished without it, but scripting allows these functionalities to be used in the heat of battle.

Contents

Scripting Commands

The following is a list of commands which have no use apart from scripting; they do not influence gameplay directly.

bind

Main article: bind

The simplest command is the bind command. It will cause a certain key to execute a certain action, whether that action is a setting, a command, or a script.

bind [KEY] [COMMAND]

Quotes can be optionally placed around the key and/or the command. However, the commands will need to have quotes when it has spaces in between the values and the command, so that the console can interpret it as one command. An example would be bind mouse1 "say texthere", where quotes are needed around "say texthere" because of the space between the two phrases.

bind [KEY] "[COMMAND 1];[COMMAND 2];[COMMAND 3]"

Quotes can be optionally placed around the key, but must be present around the commands, as the console will not interpret consecutive commands if quotes are not present.

Note: The command say "Example Text" is correct, but bind <KEY> "say "Example Text"" is not. This is because the quotes are misinterpreted, and quotes inside of quotes are unnecessary due to commands automatically stopping at every semicolon.

When a key is bound to a string starting with a plus, the same command(s) will be executed when the key is released, except the first plus will be replaced with a minus. For example, bind w +forward will make pressing W execute +forward and releasing W execute -forward. Note that this only effects the first command, and other commands will not be negated. See alias for more information. This bind will make the player move forward while they have W held down.

toggle

This command allows a cvar to be toggled between two or more values. If no values are specified, defaults to toggling between 0 and 1.

toggle tf_bot_quota normal fill match

bindToggle

BindToggle may be used to bind a key to toggle a cvar between 0 and 1. It cannot be used for values besides 0 and 1.

bindToggle o sv_cheats

incrementvar

This allows for variables to be increased or decreased repeatedly by a set amount.

bind MWHEELUP "incrementvar fov_desired 75 90 1"
bind MWHEELDOWN "incrementvar fov_desired 75 90 -1"

This will cause the field of view to increase when scrolling up, and to decrease when scrolling down

Note: Incrementvar will cause the value to wrap around if it gets too large or too small. In this example, once the field of view hits 90, it will drop down to 75, and vice-versa.

alias

Main article: alias

An alias allows multiple commands to be referenced by a single command. This is effectively shorthand, and it is most useful when a series of commands need to be called multiple times. Alias names cannot contain spaces. They may contain underscores, numbers, symbols, and are not case-sensitive (only when being created, when removing an alias it is case-sensitive).

After running the command alias foo "echo bar", typing foo in the console will execute echo bar. After running the command alias foo, typing foo in the console will no longer do anything. If the alias was created with uppercase letters (such as alias fOO "echo bar"), typing alias foo will not remove the alias, but alias fOO will.

Aliases may begin with a plus or minus character. This allows them to be used in conjuction with

bind

to negate several commands when a key is released. For example, this script allows a player to move diagonally with a single key:

alias +diagonal "+moveleft; +back"
alias -diagonal "-moveleft; -back"
bind z "+diagonal"

Releasing Z will execute -diagonal in this script, whereas simply typing bind "z" "+moveleft; +back" would result in the game never running -back when the player releases the key. This results in the player moving backwards continuously.

exec

This command will execute another file. This means that complex scripts can be stored in other files, so as not to clutter up more general files.

exec autoexec.cfg

This script will execute the player's autoexec script.

echo

This command will cause text to be printed to the console. This is very useful for debugging.

echo Scripting is; echo very useful

This will print out Scripting is and very useful on two separate lines. This is because a newline is added to the end of any text passed to echo. Spaces are only parsed if they are between words, or if the echoed text is between quotes, as in the next example:

echo " Scripting is very useful.   "

The extra spaces will be printed out, since the string is delimited by quotation marks.

Note: It is not possible to print out the " character, as its meaning will be misinterpreted. However, you can print single quotes: that is, the ' character.
Note: Echo occasionally will misprint strings that are not delimited by quotation marks. As a general rule of thumb, it is better to enclose what you wish to print within quotation marks. It also makes it easier to read for humans.

wait

This command will make the game wait a given number of frames before executing the next command.

Warning: Wait commands are disabled on certain servers. This will cause certain scripts to fail, and may (in semi-rare cases) cause the game to crash. See Wait Testing for help to protect against this.
echo Why did the chicken cross the road?;wait 300;echo To get to the other side!

This script will wait 300 frames (1 second at the default max FPS) before printing the punchline.

Class-specific CFG Files

When switching to a certain class, the game executes the corresponding CFG file (if it exists), named after the given class.

scout.cfg
soldier.cfg
pyro.cfg
demoman.cfg
heavyweapons.cfg
engineer.cfg
medic.cfg
sniper.cfg
spy.cfg

This automation lets the player have different keybinds and game settings for each class.

Launch Options

Launch options can be used to change how TF2 runs, both performance wise and functionality wise. Please see Command Line Options on the Valve Developer Community for a comprehensive list of launch options

Set Launch Options

A visual guide on how to set launch options (indicated by the red circles).
  1. Right-click on the game title under the Library in Steam and select Properties.
  2. Under the General tab click the Set launch options... button.
  3. Enter the launch options you wish to apply (be sure to separate each code with a space) and click OK.
  4. Close the game's Properties window and launch the game.

Window Options

Note that these may incorrectly setup an improper video mode not preferred by the material system, reducing performance. Where possible, you should use the in-game settings instead.

Resolution

Launch Option: -w # -h #

Description: Forces the game resolution width and height in pixels.

Refresh Rate

Launch Option: -freq #

Description: Forces the game refresh rate in Hz.

Windowed Mode

Launch Option: -windowed

Description: Launches the game in windowed mode.

Borderless Windowed Mode

Launch Option: -noborder

Description: When in windowed mode, remove the window border to allow for borderless fullscreen mode, as opposed to exclusive fullscreen mode.

Fullscreen Mode

Launch Option: -fullscreen

Description: Forces the game resolution width and height in pixels.

Peripheral Support

Disable Joystick Support

Launch Option: -nojoy

Description: Prevents the joystick system from loading, improving start-up time and memory usage. Don't use this if you intend to use a joystick with the game.

Disable Steam Controller Support

Launch Option: -nosteamcontroller

Description: Prevents the Steam controller system from loading, improving start-up time and memory usage. Don't use this if you intend to use a Steam controller with the game.

Software Support

Disable SourceTV

Launch Option: -nohltv

Description: Disables SourceTV support, improving memory usage. Don't use this if you host SourceTV on your client.

Disable Quicktime

Launch Option: -noquicktime

Description: Disables QuickTime support, improving memory usage. Don't use this if you required QuickTime support, such as for when exporting .MOV files.

Engine Options

Disable Intro Video

Launch Option: -novid

Description: Removes the Valve intro video shown when the game is started, improving loading times.

Change Beam Particle Limit

Launch Option: -particles #

Description: Limits the number of beam particles. Set # to '1' to (a limit of 512) to improve memory usage.

Precache Font Rendering

Launch Option: -precachefontchars

Description: Precaches font rendering for common characters, improving rendering time.

Disable Texture Streaming

Launch Option: -no_texture_stream

Description: Disables using lower quality textures whilst higher quality versions load, instead favouring to always instantly load the higher quality versions. Disabling texture streaming will have a performance impact on systems under video memory pressure.

DirectX Version (Windows Exclusive)

Launch Option: -dxlevel #

Description: Sets the DirectX Version used by the game; accepts many values but only '81' and '100' should be considered.
'-dxlevel 100' uses DirectX 9 and Pixel Shader 3.0, and hardware is used to determine the system's graphics capabilities.
'-dxlevel 81' is the most stable version of DirectX 8 and uses Pixel Shader 1.1. It typically has more performance than DirectX 9 versions but has a reduced feature set so should be avoided if the performance increase is not absolutely necessary.
Note: After launching the game with this once, the game should then be closed and it should be removed from the launch options in order to properly set the related configuration files.

List of key names

Hover over a key to see its scripting name. Names are not case-sensitive.

ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12

`   1 2 3 4 5 6 7 8 9 0 - = ← Backspace

Tab ⇆ Q W E R T Y U I O P [ ] \      

⇪ Caps A S D F G H J K L ; '   Enter ↵

Shift     Z X C V B N M ,   .   /   Shift        

Ctrl   Alt       Spacebar       Alt ≣ Menu Ctrl    

PrtScn ScrLk Pause

Insert   Home PgUp

Delete   End   PgDn


                 

         

Num / * -
7 8 9 +
4 5 6
1 2 3
    0     .
Mouse Button Name of Keybind
Scroll Up MWHEELUP
Scroll Down MWHEELDOWN
Left Click MOUSE1
Right Click MOUSE2
Wheel Click MOUSE3
Left Button Click (forward) MOUSE4
Right Button Click (back) MOUSE5

Useful commands

Main article: List of TF2 console commands and variables

Disguising

The disguise command takes two arguments, the first being the class and the second being the team.

Class
1. Scout
2. Sniper
3. Soldier
4. Demoman
5. Medic
6. Heavy
7. Pyro
8. Spy
9. Engineer
Team
1. BLU team
2. RED team
-1. Opposite team
-2. Same team

Thus, disguise 5 1 would disguise as a BLU Medic and disguise 7 -2 would disguise as a friendly Pyro.

Note: disguise 8 -2 (Friendly Spy) will cause the player to un-disguise.
Note: Any collection of characters and/or numbers after the class number that are not 1, 2, -1, or -2 will default the disguise to RED team, regardless of the player's current team. For example, disguise 1 3 will disguise the Spy as a RED Scout.

Buildings

The build and destroy commands each take two arguments, the first being the building and the second being the building type. The second argument is only required if it is not 0, and is currently only used to differentiate between teleporter entrances and exits.

The build command will pull up the blueprint to place a building, with an exception of the Sapper, which is wielded.

build 0 0 will build a Dispenser (Engineer only)
build 1 0 will build a teleporter entrance (Engineer only)
build 1 1 will build a teleporter exit (Engineer only)
build 2 0 will build a Sentry Gun (Engineer only)
build 3 0 will build a Sapper (Spy only)

Similarly, the destroy command will destroy buildings.

destroy 0 0 will destroy a Dispenser (Engineer only)
destroy 1 0 will destroy a teleporter entrance (Engineer only)
destroy 1 1 will destroy a teleporter exit (Engineer only)
destroy 2 0 will destroy a Sentry Gun (Engineer only)
Note: Sappers cannot be destroyed.

It is possible to use the old build commands, which used only one argument.

build 0 will build a Dispenser (Engineer only)
build 1 will build a teleporter entrance (Engineer only)
build 2 will build a Sentry Gun (Engineer only)
build 3 will build a teleporter exit (Engineer only)
build 3 will build a Sapper (Spy only) [deprecated]

Voice Menu

The voicemenu command takes two arguments, the menu number and the command number.

  • voicemenu 0
    0: MEDIC!
    1: Thanks!
    2: Go! Go! Go!
    3: Move Up!
    4: Go Left
    5: Go Right
    6: Yes
    7: No
    8: Pass To Me!
  • voicemenu 1
    0: Incoming
    1: Spy!
    2: Sentry Ahead!
    3: Teleporter Here
    4: Dispenser Here
    5: Sentry Here
    6: Activate Charge!
    7: MEDIC: ÜberCharge Ready
    8: Pass To Me!
  • voicemenu 2
    0: Help!
    1: Battle Cry
    2: Cheers
    3: Jeers
    4: Positive
    5: Negative
    6: Nice Shot
    7: Good Job
Note: If you wish to display the voicemenu, rather than fire the voicemenu <num> <num> message, the command is voice_menu_<num>: where <num> is a number between 1 and 3, and takes no arguments. For instance, to display the first voicemenu, one would run the command voice_menu_1.

Eureka Teleport

The eureka_teleport can teleport an Engineer holding the Eureka Effect to their spawn or teleporter exit.

  • eureka_teleport 0 will teleport the player to their spawn
  • eureka_teleport 1 will teleport the player to their teleporter exit

The player will see "Unknown command" in their console even though the command works.

Assorted

  • clear will clear the console of any information.
  • alias will list all currently defined aliases.
  • fov_desired (20-90) will set the field of view.
  • viewmodel_fov will set the FOV for weapon models. It ranges by default from 54 to 70.
  • r_drawviewmodel (0/1) will show (1) or hide (0) weapon models.
  • lastdisguise will cause the player to re-disguise as their last disguise. (Spy only)
  • load_itempreset (0-3) will load a particular loadout preset [A, B, C, D].
  • say message will send a message to public chat.
  • say_team message will send a message to team chat.
  • say_party message will send a message to party chat.
  • +taunt will open the player's taunt loadout.
  • +use_action_slot_item will cause the player to use their action slot item.
  • volume (0-1) will change the in-game volume.
  • taunt_by_name (name) will run a specified taunt, given the exact name of a taunt in the player's current taunt loadout, without opening the taunt menu.
  • key_findbinding (string) will list all keys bound to a string containing the given substring (case-sensitive).
  • key_listboundkeys will list all keys currently bound and their associated commands.

Advanced Scripting Techniques

Toggles

It is possible to bind a key to toggle a command which would otherwise be a press and hold command.

bind w toggle_movement
alias toggle_movement enable_movement
alias enable_movement "alias toggle_movement disable_movement;+forward"
alias disable_movement "alias toggle_movement enable_movement;-forward"

This script will cause a press of W to keep the player moving forward until W is pressed again.

Key combinations

It is possible to create a script where holding down a key changes the action of another key. For example, the following script can be used to make Alt+F4 exit the game:

alias +alt_pressed   bind f4 exit
alias -alt_pressed unbind f4

bind alt +alt_pressed

Note that pressing Alt will execute +alt_pressed, and releasing it will execute -alt_pressed.

Wait-testing

Since the wait command is integral to some scripts, it may be necessary to test to see if a server has disabled the command.

alias waitTester "alias waitTest waitPositive; wait 0; waitTest"
alias wait "alias waitTest waitNegative"
alias waitPositive "echo Wait is enabled on this server.; exec waitPositive.cfg"
alias waitNegative "echo Wait is DISABLED on this server!; exec waitNegative.cfg"
waitTester

This script relies on the fact that if the wait command is disabled on a server, the alias named wait can be defined by the user. Thus, the script creates an alias named waitTest which by default points to waitPositive, but if wait is not allowed (and can thus be defined by the user), will be redirected to waitNegative.

Loops

Warning: Loops which run without a wait command will cause the TF2 client to hang. It is highly suggested to run a looping script only after a wait testing script.

It is generally considered bad form to have one alias point to itself, as although the loop can be broken out of, it cannot be reset. Therefore, looping scripts tend to include two parts to the loop: The part that waits, and the part that loops.

bind g loopKey
alias loopKey startLoop
alias startLoop "alias loopKey stopLoop;+attack;alias redirect loop;loop"
alias stopLoop "-attack;alias redirect;alias loopKey startLoop"
alias loop "+left;wait 33;-left;+right;wait 33;-right;redirect"

This script will start looping once G is pressed. It begins by firing, and then switches the player's view back and forth every 33 frames (half of a second on most servers). Pressing G would cause the next iteration of the loop to stop, also stopping the firing.

Sequences

alias +pyrocombo "slot1;+attack;wait 32;slot2"
alias -pyrocombo "-attack;slot1"

This script will create two aliases, one to start a sequence, and one to end it. The sequence will switch to a Pyro's Degreaser and fire for 32 ticks, before switching to the Panic Attack and shooting until the button is no longer held. Sequences can also be made like this:


alias quickscope "slot1;+attack2;wait 32;+attack;wait 16;-attack;-attack2"

This script will create a sequence alias, that once activated will cause the Sniper to quick-scope his Sniper Rifle; by executing the long string of commands called a sequence. Sequences are useful in making scripts, and learning how to make one will help in the long run of scripting.

Cycles

A cycle is toggle script where there are a minimum of 3 possible options, which loop (ex, 1, 2, 3, 1). Example:

alias message_1 "say message 1.; bind x message_2"
alias message_2 "say message 2.; bind x message_3"
alias message_3 "say message 3.; bind x message_1"
bind x message_1

This script makes it so pressing the X key will cycle between making you say "message 1", "message 2", and "message 3".


Pictogram comment.png toggle, incrementvar, and multvar can often be used in place of aliases when a console variable is being changed.

Selection addons

A selection script is built onto a cycle to make it more intuitive. Selection scripts allow cycling upwards and downwards, ultimately giving more control for selecting which command(s) to run.

alias CondC_UP Cond1
alias CondC_DOWN Cond5
alias ApplyCond ApplyCond33
alias ApplyCond33 "addcond 33"
alias ApplyCond49 "addcond 49"
alias ApplyCond72 "addcond 72"
alias ApplyCond74 "addcond 74"
alias ApplyCond90 "addcond 90"
alias Cond1 "alias CondC_UP Cond2;alias CondC_DOWN Cond5;alias ApplyCond ApplyCond33"
alias Cond2 "alias CondC_UP Cond3;alias CondC_DOWN Cond1;alias ApplyCond ApplyCond49"
alias Cond3 "alias CondC_UP Cond4;alias CondC_DOWN Cond2;alias ApplyCond ApplyCond72"
alias Cond4 "alias CondC_UP Cond5;alias CondC_DOWN Cond3;alias ApplyCond ApplyCond74"
alias Cond5 "alias CondC_UP Cond1;alias CondC_DOWN Cond4;alias ApplyCond ApplyCond90"

This gives more control in what conditions to add to the player. This also allows for better freedom of selection and ease of use, as it makes scrolling through options in the cycle possible.

Randomization

Randomization is a strange and niche feature. Randomization is rarely used, as most processes aren't as useful when randomized. However, randomization can be useful for chat binds, such as for trade advertising.

Note: Due to the nature of TF2's scripting, this section will be considerably long. If you don't already have an understanding of how cycles work, the information presented may not be relevant.

alias call f1
alias cycle c2

alias c1 "alias cycle c2;alias call f1"
alias c2 "alias cycle c3;alias call f2"
alias c3 "alias cycle c4;alias call f3"
alias c4 "alias cycle c5;alias call f4"
alias c5 "alias cycle c1;alias call f5"

alias f1 "say 1"
alias f2 "say 2"
alias f3 "say 3"
alias f4 "say 4"
alias f5 "say 5"

alias +w "+forward;cycle"
alias -w "-forward;cycle"
alias +a "+moveleft;cycle"
alias -a "-moveleft;cycle"
alias +s "+back;cycle"
alias -s "-back;cycle"
alias +d "+moveright;cycle"
alias -d "-moveright;cycle"

bind o call
bind w +w
bind a +a
bind s +s
bind d +d

This script is assigning and resigning multiple alias values. When any of the WASD keys are pressed or released, the cycle command is ran, which moves the cycle command to the next value in the cycle and sets the "call" command to a value corresponding to the cycle number. This is based on the player's movement, and only changes values if the player is moving. It is possible to make this randomizer more effective by using other various techniques stated here (ex. Loops), but this example is for demonstration purposes only.

Timed action

Timed or held actions trigger when a button is pressed down for a certain amount of time. Timed actions can be used in situations where a script or command shouldn't be instantly ran the moment a button is pressed (ex. accidentally pressing a disconnect bind).

alias "+ti_zoom" "alias zoom_con zoomOn; wait 132; zoom_con"
alias "-ti_zoom" "zoomOff; alias zoom_con ; rb_tizoom-M4"
alias "rb_tizoom-M4" "unbind mouse4; wait 132; bind mouse4 +ti_zoom"
alias "zoomOn" "fov_desired 20; r_drawviewmodel 0"
alias "zoomOff" "fov_desired 90; r_drawviewmodel 1"
bind "mouse4" "+ti_zoom"

Pressing (and immediately releasing) Mouse 4 with this script loaded will have no noticeable effect, however holding down Mouse 4 for 2 seconds will cause the script to lower the FOV to 20, and hide viewmodels. Letting go of Mouse 4 at any point will undo these changes by setting the FOV to 90 and unhiding viewmodels.

This works because of the use of + and - aliases. Pressing the key +ti_zoom is bound to will redefine zoom_con to activate the script, and if left pressed for the wait duration will execute the script. However, if the button is released, zoom_con is redefined to do nothing. The key is then "disabled" by being unbound for the same wait duration, and rebound afterwards to restore use of the key.

Note: Rebinding of the key is technically redundant, as the script will not execute the timed action if the button is released. However, if the button is pressed multiple times it is possible to execute the timed action if the confirmation alias (in this case, zoom_con is properly defined as any of the presses would execute it. Unbinding the key for the same duraiton of the original wait delay ensures that the effect can't be triggered if the button is rapidly pressed.

Basic Conditionals

The basic conditional allows a script to change its behavior without running an entirely new script. By making use of a dummy alias it is possible to change the outcome of an input based on other inputs. Basic conditionals can support potentially infinitely many checks on the state of other commands, however it's unlikely that a script would need more than a few checks per conditional.

A very basic example of a conditional may look like:

alias "check_test" "alias test success; check1; check2; test"
alias "check1" ""
alias "check2" ""
alias "test" "success"

alias "fail_check" "alias test failure"

alias "success" "echo SUCCESS!"
alias "failure" "echo FAILURE!"

alias "+k_pressed" "alias check1 fail_check"
alias "-k_pressed" "alias check1"
alias "+j_pressed" "alias check2 fail_check"
alias "-j_pressed" "alias check2"

bind "l" "check_test"
bind "j" "+j_pressed"
bind "k" "+k_pressed"

The main function of this script is the check_test alias. When ran, this alias checks the other 2 conditionals, and if the checks succeed it runs the success alias. However, if one of the checks fails, the dummy alias test is pointed to run the failure alias. Simply put, when a check succeeds the checking command doesn't redirect the alias test is pointing to. If a check fails, it redirects the test alias to the alias storing the code to run when the check fails.

In this case, pressing the button L without pressing either J or K, the check succeeds and prints SUCCESS! to the console. When pressing and holding either J or K and then pressing L, the check will fail and print FAILURE! to the console.

A real world example of basic conditionals:

// Change the crosshair color when moving around

alias "+w_pressed" "+forward;   alias check_w pressed_w; chc_forward"
alias "+a_pressed" "+moveleft;  alias check_a pressed_a; chc_left"
alias "+s_pressed" "+back;      alias check_s pressed_s; chc_back"
alias "+d_pressed" "+moveright; alias check_d pressed_d; chc_right"

alias "-w_pressed" "-forward;   alias check_w; check_none"
alias "-a_pressed" "-moveleft;  alias check_a; check_none"
alias "-s_pressed" "-back;      alias check_s; check_none"
alias "-d_pressed" "-moveright; alias check_d; check_none"

alias "check_w" 
alias "check_a" 
alias "check_s" 
alias "check_d" 

alias "pressed_w" "dchk_fail; chc_forward"
alias "pressed_a" "dchk_fail; chc_left"
alias "pressed_s" "dchk_fail; chc_back"
alias "pressed_d" "dchk_fail; chc_right"

alias "check_none" "check_s; check_a; check_d; check_w; dmy_check"
alias "dmy_check" "chc_success"

alias "dchk_fail" "alias dmy_check chc_failure"
alias "dchk_reset" "alias dmy_check chc_success"

alias "chc_failure" "dchk_reset"
alias "chc_success" "chc_default"

alias "chc_default" "color0"
alias "chc_forward" "color1"
alias "chc_left"    "color2"
alias "chc_back"    "color3"
alias "chc_right"   "color4"

// Binds
bind "w" "+w_pressed"
bind "a" "+a_pressed"
bind "s" "+s_pressed"
bind "d" "+d_pressed"

// Colors
alias "color0" "cl_crosshair_red 0; cl_crosshair_green 255; cl_crosshair_blue 0"        // Default color when not moving
alias "color1" "cl_crosshair_red 0; cl_crosshair_green 0; cl_crosshair_blue 255"        // Color when moving forward
alias "color2" "cl_crosshair_red 255; cl_crosshair_green 0; cl_crosshair_blue 255"      // Color when moving left
alias "color3" "cl_crosshair_red 128; cl_crosshair_green 212; cl_crosshair_blue 255"    // Color when moving back
alias "color4" "cl_crosshair_red 255; cl_crosshair_green 140; cl_crosshair_blue 25"     // Color when moving right

This script will change the color of the user's crosshair as they walk around with the WASD keys. An important note this script takes advantage of is that when a check fails it can do several things instead of just changing the dummy command for testing. When a check fails the crosshair will change colors, and also change the dummy command to fail the check. This means when several buttons are released, the crosshair's color will properly change to the most recently pressed key.

Commenting

As scripts get longer, the need for well-named aliases grows. However, it is not always sufficient to explain what an alias does simply by its name. Adding a pair of forward slashes (//) will turn the rest of the line into a comment–it will not execute any actions on the text.

voicemenu 1 6 //Activate Charge!

Since it is not obviously clear what the voice command is, a comment can explain it.

Noteworthy scripts

There are several notable scripts that have affected gameplay. Some of these are patched out, while others remain functional.

Patched scripts

Pistol scripts

Originally, the Pistol could be fired almost as fast as the human hand could press a key. Scripts were created to simulate this rapid pressing by holding down a single key.

August 13, 2009 Patch: The Pistol now fires at a fixed rate, not based on the speed of pressing the fire button.

Chargin' Targe turn scripts

Originally, the keyboard commands to turn left and right were not treated the same as the mouse commands. The Chargin' Targe was the first weapon to create a restriction on how quickly a player could turn, therefore Valve put a limit on mouse turn-speed, yet forgot to apply the same restriction to the keyboard command that resulted in the same action. Scripts were created to rebind the turning controls when a player charged, circumventing this restriction.

June 23, 2011 Patch: Fixed an exploit with the Chargin' Targe that allowed greater turning control than intended.

Air crouching scripts

Originally, players could crouch as many times as they liked in a single jump. By binding a script to crouch and uncrouch as rapidly as possible, the engine could be exploited to make it difficult to properly register shots on jumping targets.

March 6, 2009 Patch: Players can now only duck twice in the air.

Idling Scripts

Most servers seek to prevent players idling for drops. Players can try to outsmart these systems with scripts that simulate basic movement.

An Active Solution to an Idle Threat requires players to accept a pop-up notification in order to continue to get drops.

Current Scripts

Weapon Viewmodel Hiding Scripts

There are a large number of scripts which toggle the weapon viewmodel depending on which weapon slot is selected for a class. Players often make their viewmodels invisible to clear up the screen, but make items like melee weapons, PDAs, watches, and so forth visible because these models indicate important information. For example, the Spy relies heavily on his viewmodel to determine when he is cloaked, when his Cloak is disturbed, and when the Dead Ringer activates. Other classes use the melee animations to judge when their attacks will hit.

Weapon Zoom Scripts

By changing your FOV, this script creates the visual effect of zooming in with whatever weapon the user is holding. It can usually be toggled between a zoomed and normal (unzoomed) version.

Sentry Jumping Scripts

Since the Engineer Update, Engineers have been able to pack up and carry their Sentry Guns. Simultaneously introduced in the update, the Wrangler allows Engineers to Sentry jump with their Sentry rockets. With extremely fast inputs, it was discovered that a player could Sentry jump and successfully pack up their Sentry before they were launched away.

While a human can repeat this feat, it is difficult. Some players made scripts which could reliably execute the commands in the right order at the right speed allowing them to make a Sentry jump while carrying their Sentry every time.

Note: The Rescue Ranger can circumvent this necessity, as it can pick up buildings at range for 100 metal.

Gunslinger Scripts

Since it can be troublesome to destroy then rebuild a Combat Mini-Sentry in the heat of battle through the PDA, some players have scripted the destruction and rebuilding of their Combat Mini-Sentry with the click of one or two buttons. Such a script is especially useful when using the Frontier Justice, as the player gains practically instant access to revenge crits when needed.

Sensitivity and Control scripts

Some players prefer different mouse sensitivities and control schemes for some classes. For example, changing from the Medic, which doesn't require fine aiming, to the Sniper, which encourages high precision headshots, a player may wish to change their mouse sensitivity. These scripts alter control schemes and mouse settings on a per class, or even per weapon, basis.

Charge Dash Scripts

Since timing a charge and jump can be difficult, some players may use a quick script that binds the two actions to a button so that the charge dash will cover the maximum amount of distance possible. The player is still required to swing their melee weapon normally to end the charge though.

Quickscope Scripts

Many players find it difficult to scope in and fire straight after to get a quick headshot. There are scripts that will zoom in and fire just by clicking one button. This does require players to aim outside of the scope, though.

Rocket Jump Scripts

In order to Rocket Jump to a maximum height or distance, it is required that the player jumps, crouches, and fires their rocket at roughly the same time. This can be easily scripted to occur with the press of a button.

Auto-Disguise Scripts

For Spies who find manually disguising to be a hassle, this script automatically disguises as a chosen class after the player attacks with any weapon. Auto-disguise can usually be toggled and customized to choose a disguise to use.

ÜberCharge Broadcasting Scripts

With this script, activating ÜberCharge as Medic will also write a custom message in team chat to alert your teammates about your activation, in order to encourage your team to push ahead with you. A similar script, upon activation, plays the "ÜberCharge Ready" voice command while writing in team chat that you faked your Über to fool the enemy team.

Medic Radar

This script only works for Medic, as it lets you press a button to temporarily set the autocall percentage to a very high number. This makes it so that you can see the locations of nearby teammates. Script:

alias "autocall_default" "hud_medicautocallersthreshold 75.730003/Custom Threshold"
alias "autocall_all" "hud_medicautocallersthreshold 150"
alias "+radar" "autocall_all"
alias "-radar" "autocall_default"
bind [KEY] "+radar

Kill-Bind Scripts

Main article: Suicide

In certain circumstances, such as when cornered by a Medic wielding the Ubersaw, it can be beneficial for a class to be able to kill themselves quickly (in this case, to deny the Medic Über) with a key bind (for example, bind k kill). Although mostly only relevant in competitive play, there are occasional uses in public servers, often for comedic effect instead of to benefit gameplay. The killbind can be set to explode you if you use explode instead (for example, bind k explode). There is no difference between these two mechanically.

Null-Cancelling Movement Scripts

In stock TF2, pressing two opposing movement keys at once (such as "A" (+moveleft) and "D" (+moveright)) will cancel all movement and render the player immobile, which can be a fatal mistake during battle. This script makes it so that the direction of the last key pressed will be used instead. For example, pressing "A" will make the player go left, and pressing "D" while still holding "A" will make the player go right instead of stopping.

Chat Bind Scripts

Chat bind scripts are designed to post a pre-written message in the in-game text chat. Typically, users will bind these scripts to a key on their keyboard for easy repitition. These scripts can vary from user-to-user, and can say anything within the text limit, depending on what a player would want to say. Some common binds are used for team co-ordination, such as a bind to tell a team that their Medic has popped an ÜberCharge. Other common binds are used for banter, such as messages upon kills and/or dominations. Another variation on this is a trade offer bind, where it sends information to the chat about a possible trade offer. This type of script can also be automated to send these offers every couple of minutes.

Voice Toggle

This script enables you to voice toggle, instead of push-to-talk. Script:

bind [KEY] mic_toggle
alias mic_toggle mic_enable
alias mic_enable "+voicerecord; alias mic_toggle mic_disable"
alias mic_disable "-voicerecord; alias mic_toggle mic_enable"

Notes

  • Each config file is limited to one mebibyte (1.04858 megabytes) of information, though this restriction can be circumvented by exec-ing another config file at the end of the first.

See also

External links