There are some unique features in TES script that should be explained before we go into more detail.
Beginning and ending scripts
Begin Script_ID
End
End Script_ID
Every script must have the Begin and End tags. The specified name will also be the ID you will reference the script by (be it from other scripts or inside the TES CS object windows). A script may start out with comments, but the first line of real code must be "Begin xxxxxxxxx".
As with other objects, it is recommended that you give your scripts a unique tag. I usually use GBG_Scriptname. This ensures that your scripts are easily identified, they all are neatly listed in one block in the scripts list, and there is little danger of conflicts with other mods using the same name. Using leading underscores e.g. _Scriptname is not recommended.
If you want your scripts to appear at the top of the list of scripts, put a 1 in front, for example, 1YAC_ScriptName
General syntax for functions:
Functions are not case sensitive, but using the case sensitive form as suggested by Bethesda (e.g. GetSpellEffects instead of getspelleffects) makes scripts easier to read, so it’s recommended to keep it that way.
"Object_ID"->Function, [parameters]
This is the format for all functions that act on or refer to a specifiable object in the game world. The "arrow" or "fix" designates which object a function will be performed on. The "object_ID" is the unique ID that is given to each object in the editor (usually the first field in any object window). You need this ID, not the Name! If you call a function without a designated Object-ID, the function will be performed on the default object, which is the object the script is attached to.
This is not to say that there might not be another object referenced as a parameter:
"Object_ID1"->Function, "Object_ID2"
Notes:
Functions with a "fix" will only compile if the object has already been placed into the game world in the editor (with at least one reference), otherwise the script will not compile. If you compile the script and then delete all references, the game will give errors on load and CTD.
More than one function may be used in a set expression, but the functions always apply to the same reference. For example:
set SomeVar to ( player->GetStrength ) + ( player->GetEndurance )
and
set SomeVar to ( player->GetStrength ) + ( GetEndurance )
will both have the same effect, and specifying different references will not work.
Referencing non-unique items with the "fix" will usually perform the function only on the first reference of the object! So using this in a global script:
"cliff racer"->ModCurrentHealth -1000
will not have the desired effect, it will only kill one of the annoying bastards. However attaching a script to the creature with just
ModCurrentHealth -1000
Would do the trick, because every reference of the cliff racer will have the script running, and apply the function to itself. Note that this does not apply to all functions (e.g. SetHealth in the above example would affect all references the player has not yet encountered).
A number of functions refer only to the player or not to an object at all, and are therefore using the fix is meaningless or may produce errors. E.g.:
If ( GetPCRank == 0 )
If ( CellChanged == 0 )
FadeOut, 2
General syntax: Commas, parentheses and spaces
TES Script is not too picky about syntax. Case mostly doesn’t matter, commas can be left out, and spaces are mostly ignored. Nevertheless I would advise adhering to the following principles:
• Either avoid commas, or always use commas: inconsistent usage can cause problems.
• If the ID contains a space or begins with an underscore, you must use quotation marks: "Object ID" or "_Object_ID". Better to avoid spaces altogether: Object_ID
• Get used to always leaving spaces around parentheses and operators, sometimes it seems to cause problems if you don't: if ( variable == 1 ), not: if (variable==1).
While this doesn’t matter most of the time it generates weird and almost untraceable errors sometimes, so you are much better off always leaving a space.
• The fix (->) is a little more complicated. If IDs are contained in quotes, you should not leave spaces around the fix:
"Sirollus Saccus"->GetItemCount netch_leather_greaves
The above will work, but spaces around the fix would cause problems. (Thanks to Simpleton and DinkumThinkum for this info.) However, since it has also been reported that a lack of quotation marks can cause problems in combination with spaces round the fix, I'm going to recommend that you don't leave spaces round the fix at all (should be fine in all cases).
Comments
Comments are marked by a semicolon ;. Comments can be added in their own lines or behind lines with code
; enter sneak mode
Fargoth->ForceSneak
Fargoth->AiTravel -11468.595,-71511.531,173.728 ;goes to tree
Indentation / using tabstops
For your own sake, use proper indentation (tabstops) for if-elseif constructs – makes it much easier to keep track of them, so you don’t forget an endif at the end. In the tips and tricks section you will find a link to an external EMACS editor mode for TES script that will do automatic indentation.
If ( variable1 )
If ( variable2 )
[do something]
endif
endif
is better than
If ( variable1 )
If ( variable2 )
[do something]
endif
endif