Tip 11 - Scripting

Ok, here is how the scripting system in halflife works.
Scripts can either be entered directly at the console, or loaded from .cfg files.
The files config.cfg and autoexec.cfg are loaded every time.
soldier.cfg, scout.cfg etc are loaded when that class is chosen (usually, see setinfo) and 2fort.cfg etc when that map is started.

Now, the console is accessed (by default) via the 'tilde' key, which is the key just below the escape key, top left of your keyboard.
If you don't have an american keyboard, it won't have a tilde on it though :)

Now, by default, the console is diabled. To enable it, you need to do one of two things.
Add '-console' onto the shortcut you use to run halflife.
(Right click it, properties, change where it says program: hl.exe ... by adding -console on the end)

Or put the line 'console 1' in your config.cfg (It should replace a line which says 'console 0' or be further down the file than that line)

Ok - now, on to the meat.

Cvars. A very large number of commands you can use at the console are cvars. I'll use 'fov' as an example.
Typing just the cvar on its own, will show you its current value. fov defaults to 90, so you should see 90' when you type 'fov' and hit enter.
If you type 'fov 30' then it will change the value to 30, so that in the future typing 'fov' will return that value.
It will also do something in the game too - in this instance change your field of view to that many degrees.
30 is pretty well zoomed in. 90 is default, putting it above 180 does bad things, putting it negative or bigger than 360 does VERY bad things.
Now, to get it back. Type 'fov 0'
This resets it to the default.
Incidentally, you can change the default too, the command is 'default_fov'

Right. Next up, setinfo.
Setinfo works pretty much the same, actually. The command format is 'setinfo name value'
So 'setinfo ec 1'
This sets 'ec' (which incidentally controls whether class configs should be automatically run) to 1 (which means 'yes, they should')
Such variables often only take notice of the settings 1 and 0, meaning 'yes' and 'no'

Right. Now for a list of commands.
+det5; detdispenser
You seperate commands by a semicolon ';' and it executes the commands one after another. (That list starts setting a 5 second detpack, then detonates the dispenser)

Ok, now alias.
alias newcommand "command1; command2; command3"
This creates a new command (new command) and setting off that command is identical to running the commands in the list.

Finally, actually getting these commands to do anything.
bind KEY "commadn1; command2; command3"
That makes the command list get set off when you press the given key.
One tiny adjustment to this:
bind KEY "+command1; command2; command3"
This is just the same, except that a + command has a partner, the -command, and it would mean that '-command1' is set off when the key is released.
This is useful for commands whih are 'start and stop' like, for example, walking forward.
You don't want to have to hammer the forward key, just hold it until you want to stop moving.

You can also create + and - commands of your own, using alias.


And, really, thats it. Apart from a huge list of available commands and cvars, which you can look up (i.am/tfc is a good source)

Maybe a few more examples.
Here's a simple script a sniper will find useful. Instead of holding the fire-button to charge the shot, and release it to fire, they can press fire once to start chanrging, then press it again to stop.

alias start_attack "aastop; +attack"
alias stop_attack "aastart; -attack"
alias aastart "alias myattack start_attack"
alias aastop "alias myattack stop_attack"
bind MOUSE1 myattack

aastart

Looks pretty confusing, eh? Well, it's longer than it needs to be, so that I can explain a bit more.
First of all the lines which do the work.
We create a command, start_attack, which calls 'aastop' (huh? Wait, thats a command wwe create in a moment) and then calls '+attack' which is the command to start firing, usually tied to your left mouse button.
Then we do something similar creating stop_attack, which calls aastart, and -attack - which is to stop firing.
So apart fom these 'aastart' and 'aastop' bits seems sensible.
Now the supporting lines, we define these 'aastop' and 'aastart' commands.
aastart is itself an alias - it makes the new command 'myattack' and tells it to be 'start_attack'
Similarly aastop makes my_attack call stop_attack.
Now, don't get confused, these lines only happen when they get called - so my_attack doesn't do two things.
And, even better, when one is called it makes my_attack forget what it used to do - it only does the new thing.
The last bit is making it so we can call it, we bind mouse1 (the left mouse button) to triggering my_attack.

Ok - lets see it in action.
First the 'aastart' line runs. This sets my_attack to be 'start_attack'

Then we press the mouse button down.
This calls my_attack (because of the bind) which in turn calls start_attack, which calls aastop (changing my_attack to now call stop_attack) and then calls +attack - which starts firing.
For the sniper rifle, this means the red dot, and charging up happens.
Now we relase the mouse button. Because it ISN'T a + command, nothing happens, so we keep on chargin up.
Yay! The first bit works! :)

Now we press it a second time. my_attack is now aliased to stop_attack, so that runs. It calls aastart (which connects my_attack to start_attack) and then calls -atack, which stops firing.
For the sniper, stopping firing is actually taking the shot - which puts movement speed to normal, gets rid of the red dot, and, oh yes, hopefully kills something.
So that's worked too.
Finally we release the mouse button, which again does nothing. And my_attack is connected to start_attack, so we're back ready to prime another shot.


A similar script (which can be made shorter quite easily by moving the aastop lines into the commands that call them) can be made for grenades, and is kind of useful - you'll see it on many sites.



Lets have another example of what you can do with scripts.
Comms scripts are very useful - binding a key to quickly tell your teammates something - but you quickly run out of keys.

So lets make it so that holding down shift and pressing a key activates a different comms bind to not holding down shift.

alias commbind1 "say_team Help! I need help!"
alias commbind2 "say_team Thanks!"

// This is a comment, by the way - it does nothing
// but is useful for me to show you how a script works
// Those lines are, fairly obviously, the actual messages we will use

alias +myshifton "bind F12 commbind2"
alias -myshifton "bind F12 commbind1"

// thats the magic

bind SHIFT +myshifton
-myshifton

// And there's the point

Not the nicest way to do it, but effective.
If you press shift, F12 will connect with commbind2, and say 'thanks' when you press it
If you then let go of shift, F12 will (re)connect with commbind1, and say 'help'

Have fun, you'll find a lo of commands out there you can play with, and it can get as complicated as you like.


*addition for TF1.5*
Some time ago, special message binds were added, and they seem to be all the rage at the moment.
So I'll tell you them here:
say_team "I have %h health, %a armour and the person in my crosshairs is %i"

The %h %a and %i get replaced by numbers (or a name for the last one) autromatically when the command is run.

The 'standard' bind at the moment is
bind z "saveme; say_team Medic/Engineer please, current status %h/%a"
saveme is the 'MEDIC!' shout, and the say_team does what it says - reports how badly you need a medic.

There you go - hopefully this will mean that you have less problems editing other peoples scripts, and making your own.

Oh, some last notes - scripts don't go away - if you put that sniper bind in your sniper.cfg, for example, then when you changed class back, it'd still be there - so you'd have to put 'bind MOUSE1 +attack' into each of your other class configs.
And to use a script you find on the web, just save it in its own .cfg file, and use 'exec whatever.cfg' (where whatever is the name you chose) to run it.
If you want it to run from a certain class, you can put that exec line in the class config, or for all classes, your autoexec.cfg is a good place.

Be careful editing your config.cfg - halflife tends to save its own settings in there, and will overwrite your changes.