script
script
is a console command available in all Source games since
Left 4 Dead 2.
It is available in all games that have a Squirrel implementation of VScript, namely these.
Syntax
script <code>
Description
It executes Squirrel code from the root table. The code can contain spaces even without using quotation marks ".
Limitations
Semicolons
Semicolons ; can be used for scripting needs only inside of quotes because the developer console otherwise treats them as a delimiter for console commands.
- First way to use them is by enclosing whole code in quotes. In which case those 2 quotes are the only quote symbols allowed because the command is searching for the ending quote and it cannot be escaped in console
script "local a = 666; for(local i; i < 10; i++) { printl(i + a) }"
- Other way to use them is possible if they are within quotes in a string.
script printl("I can print ; but now I need a way to execute a string")
- Utilizing
compilestring
which compiles a string into a function it's possible to usefor
orlocal
keywords while also using quote symbols for strings
script compilestring("for(local i = 0; i < 10; i++) {printl(\"I can now do this: \" + i)} printl(\"My only limit now is max 255 characters in a console prompt, and the up arrow to get previously run command will only give 253 characters!\")")()
- Separating non-statements without semicolons and methods above can be done using , comma.
script printl("i = 0"), i<-666, printl("i = " + i)
- Separating statements can be somewhat done using statement blocks.
script function f() { {i<-0} while(i++<10) printl(i) }
Command parsing
When script command is issued all the text from start of the command (including spaces) up to the ending semicolon is taken, first 6 characters from it are cut and the rest is run as a script. This in result means that if there is any space before script command it will cause errors.
The following example shows script command issued with 3 spaces before it. ]
represents start of the console line.
] script printl(666)
- Command above will run the script ipt printl(666) resulting in error.
- The same applies to multiple script commands separated by ;. There must be no space between the ending semicolon and the start of next script command i.e. script printl("print1"); script printl("print2") will throw a script error, but script printl("print1");script printl("print2") will not.
Finding command issuer
- activator or caller, which are automatically created during I/O operations on entities with a script scope, wouldn't make much sense in this context and aren't created by script command. Neither is self, which one could reasonably expect to contain the player issuing the script command. Getting the handle of a player running the command is not possible with a single "apply to all situations" method and
Team Fortress 2 branch based games only allow the server to use the
script
command in which case it could be issued by clients only via rcon.
- If a client is connected to a server and has the ability to issue this command, they can figure out their player entity by checking status and using the
GetPlayerFromUserID(userid)
function if it's available. In the case ofor
, unique special targetnames are available and usable for example
Entities.FindByName(null, "!bill")
.
- If the player is a host of the server, they can find themselves using
Entities.FindByName(null, "!player")
.
- Other means include using ent_fire and the RunScriptCode input in which case the issuer of the command is set as the activator and caller. A player can target themselves for example using
ent_fire !activator RunScriptCode "::storing_my_handle_as_global <- self"
. See also: Generic Keyvalues, Inputs and Outputs/Inputs#VScript.
Examples
script printl( GetMapName() )
Prints the name of the current map in the console.
script player <- Entities.FindByClassname(null, "player"); script player.SetMaxHealth( 200 )
Using a variable, find the player with the lowest entity index then set their max health to 200.
script { player <- Entities.FindByClassname(null, "player") } { player.SetMaxHealth(200) }
The same code, but as a single console command, achieved by using curly braces to bypass semicolons. Note that in this example, one pair of curly braces would suffice; if there is no nesting, putting every other statement in curly braces is sufficient. Note also that the statement player <- ...
despite the curly braces, creates a table slot in the root table that persists after the closing brace. If the player variable should be a local variable, its assignment statement must not stand alone inside curly braces, since its scope ends with the closing curly brace.
When executing multiple complicated commands repeatedly using the up ↑ and down ↓ arrow keys in the console it may even be useful to add a comment in the command, for example the following.
script /* SET MAX HEALTH 200 */ { player <- Entities.FindByClassname(null, "player") } { player.SetMaxHealth(200) } // SET MAX HEALTH 200
Squirrel will never see line comments starting with //
because the developer console sees and removes them first.
Block comments /* */
can also be used because Squirrel supports them!