-
Notifications
You must be signed in to change notification settings - Fork 0
Scripts
Script for SL Triggers, or SLTScript, is primarily a text file using a simple marker-to-enclose tokenization strategy. Lines are tokenized by splitting on whitespace, except when fields are enclosed in either double-quotes (""), dollar-double-quotes for string interpolation ($"") or square brackets ([]). Enclosed strings may contain whitespace, and embedded double quotes are escaped by doubling them ("").
The legacy option of .JSON is no longer supported.
In cases where a bare word is detected and not determined to be a function or variable name, it will be interpreted as a string literal ("").
; $msg is a valid variable name, and this is an example of a comment
set $msg "Hello world"
; this prints a message to the console
msg_console $msg
; this jumps to the [done] label
goto [done]
; this code would not be run
[done]
; semi-colon is a comment-to-end-of-line marker
Empty lines are ignored.
Each command and its parameters must reside on one line, with any amount of separating, trailing, or preceding whitespace. Commands can be either intrinsics (part of the SLTScript language) or functions (from extension libraries).
Generally, you won't need to worry about the distinction between 'intrinsics' and 'functions'; you can just refer to them all as 'commands', but 'intrinsics' tend to be faster than 'functions'.
Scripts run each command in sequence until they encounter a return or reach the end of the script. This allows for very long-running scripts.
Data types are preserved and coerced, with string as a default fallback. Forms will be "coerced" to their FormID.
All variables are ultimately strings. SLTScript automatically handles conversion between types as needed.
For purposes of SLTScript, you have the following data types available:
| Data Type | Description |
|---|---|
string |
Sequence of characters, delimited by double quotes, e.g. "Hello, world!". |
label |
Sequence of characters, delimited by square brackets, used for goto/if targets, e.g. [label target]. This form allows spaces in the label. |
int |
32-bit integer numeric value. Can be expressed in hexadecimal form by using a 0x prefix. e.g. -12, 0, 100, 0x23
|
float |
floating point (float) numeric value. e.g. -12.23, 0.44, 100.48
|
bool |
boolean value, expressed either true or false
|
Form |
Form values |
Alias |
Alias values |
map |
A set of key-value pairs associated with the variable name. See the Maps section below. Reference values by using map key notation e.g. $var{$mapkey} where $mapkey contains the value of the key; literals may be used e.g. $var{literalvalue} will look for a value with the key "literalvalue"
|
list |
An ordered set of values, sharing a common type. Once a list's type is determined, future assignments will coerce to that type rather than changing the type of the target variable. |
A variable becomes a map when you assign to it using a map key. Map keys are specified using map key notation.
set $keyvalue "somekey"
set $mapvariable{$keyvalue} 23
set $intvalue $mapvariable{$keyvalue}
If you do not use a variable for the map key, it will assume the specified map key is a string literal.
; this is identical to the previous example
set $mapvariable{somekey} 23
set $intvalue $mapvariable{somekey}
The data type of the assigned value will be retained for coercion later as needed. This means you can do this reliably.
set $mapvariable{test} = true
if $mapvariable{test}
; this will run so long as $mapvariable{test} is 'truthy'
endif
A variable becomes a list when you assign to it using a list index. List indices are ALWAYS resolved as an int. This means if you try to use a variable that is not an int, the variable will be coerced to an int, which in some cases could cause it to always resolve to 0 (i.e. when attempting to use a string as the list index when the string is not a stringified int).
; an instance of a list with a list index
$listvar[0] = 12
Unlike maps, which can contain multiple data types, a list contains only a single type. So a list isn't just a list, it is a string list, or an int list, or a Form list, or a label list.
If a variable has never been assigned to, or is not currently a list, the first indexed assignment establishes the list's type.
$listvar[0] = 12
; listvar is now an "int list", containing integers; future assignments will try to coerce data to "int"
$listvar[1] = "23"
; $listvar[1] is 23, because "23" (string) coerces to 23 (int)
$listvar[2] = "thirty-four"
; $listvar[2] is 0, because "thirty-four" (string) coerces to 0 (int) because it isn't an actual number
You can declare a variable to be a specific list type (that is, force it to be treated like that type). This is most useful when initializing a list in order to force the stored data type. The syntax is in the form of <type> <varname>. For example:
int[] $listvar
; $listvar will be treated like an list of integers
set $listvar[0] "one"
; $listvar[0] is 0 (int) because "one" (string) coerces to 0 (int) because it is not actually numeric
This does not change data. If you have a list of strings containing the value "apple" and cast it to "int[]" (list of integers) and attempt to retrieve the "apple" element, it will return 0 because as an int, "apple" cannot be coerced and defaults to 0.
Note also that if you are careful with the first assignment to a list, this pre-declaration is not required.
Available list types and their declarations:
| Declaration | List Type |
|---|---|
string[] |
list of strings e.g. "Nord", "Breton", "Argonian" |
bool[] |
list of bool values e.g. true, false |
int[] |
list of int values e.g. 23, 34, 45, 0x23, -14 |
float[] |
list of float values e.g. 1.23, 4.0234, -32 |
Form[] |
list of Form values e.g. $system.partner, $system.partner2, $system.player |
Alias[] |
list of Alias values |
label[] |
list of labels e.g. [here], [there], [somewhere] |
For any function that expects a Form like thing (e.g. Actor, ObjectReference, Form, ActorBase), you can provide any of the following:
-
Special Scoped Variables
systemvariables and perhaps variables in other scopes such asrequestmay return Forms and can always be used where a Form is expected -
Variables If you perform a function that returns a Form and set a variable to store that result, you should be able to trust that using that variable where a Form is expected will work. For example:
actor_name $system.player set $targetActor $$ ; anything that expects an Actor should work with $targetActor actor_isvalid $targetActor ; $$ will either be true or false depending on the validity of $targetActor -
FormID Strings You can also directly provide a FormID string; likewise, setting a variable to such a FormID string will also allow it to be used; FormID strings can be provided in several formats:
- <modfile>:<relative formid> this is a commonly used format e.g. "skyrim.esm:0xf" or "skyrim.esm:15" for a septim (modfile: "skyrim.esm", formid: 0xf or 15)
-
<relative formid>|<modfile> another commonly used format e.g. "0xf|skyrim.esm" or "15|skyrim.esm"
-
<relative formid> keep in mind the difference between an ESL flagged vs a non-ESL flagged mod; the ESL flagged mod has only (it's still a lot) 0xFFF room to work with, whereas other mods have the full 0xFFFFFF
; this is a relative FormID and 'Quick Start - SE.esp' is not ESL flagged, so we can safely assume the whole 0xFFFFFF is available ; although the high order bits aren't specified, for sake of discussion, let's assume Quick Start is at 0x23 set $quickstartchest = "0x003881|Quick Start - SE.esp" ; this is one of the containers in the Quick Start mod form_dogetter $quickstartchest GetFormID ; $$ would now contain something like 587,217,025 (i.e. int value of '587217025'), which is base 10 for hex value of 0x23003881 form_dogetter $quickstartchest GetName ; $$ would now contain something like "Chest" or whatever the name is from the mod
-
<relative formid> keep in mind the difference between an ESL flagged vs a non-ESL flagged mod; the ESL flagged mod has only (it's still a lot) 0xFFF room to work with, whereas other mods have the full 0xFFFFFF
-
<absolute formid> not so common but useful for local tinkering; note that absolute formids will change if your load order changes
-
accepts decimal or hexadecimal formid values can be specified as either decimal or hexadecimal; hexadecimal requires a leading
0x
-
accepts decimal or hexadecimal formid values can be specified as either decimal or hexadecimal; hexadecimal requires a leading
SLTScript supports the following literals and literal types.
| Literal | Description |
|---|---|
| string literals | Anything surrounded in "", e.g.: "string", "Hello world!"
|
| numeric values | Any integer or float value. Integers can be expressed in hexadecimal notation e.g. 0x12
|
true |
boolean: true |
false |
boolean: false |
none |
Form: none |
SLTScript supports scoped variables:
-
Local variables:
$variableName|$local.variableName- Available only to the currently executing script -
Thread variables:
$thread.variableName- Available to any script on the current thread/callchain -
Target variables:
$target.variableName- Available to any script running on the target-
Target scope extension:
$target.<otherActor>.variableName- Allows access to another target's variables (i.e. not$system.self)
-
Target scope extension:
-
Global variables:
$global.variableName- Available to all scripts, persistent across saves
Variable names can include any of the following characters after the scope: A-Za-z0-9._.
Note: You can have whitespace inside a variable statement only if it is inside the target sub-scope, list index, or map key. For example:
; these are valid
$target.<otherActor>.varname
$target.< otherActor >.varname
$map{42}
$map{ 42 }
$list[0]
$list[ 0 ]
; but these are not
$target<otherActor>.varname ; missing period between "target" and "<"
$target. <otherActor>.varname ; extraneous space between "." and "<"
$target.<$otherActor> .varname ; extraneous space between ">" and "."
$map {42}
$list [0]
system scoped variables are typically read-only and offer various system-level pieces of information.
| Variable | Returns |
|---|---|
$system.self |
Actor - the Actor the script is targeting/running on; for some triggers this will always be the Player |
$system.player |
Actor - the Player |
$system.actor |
Actor - the Actor returned from certain functions e.g. util_getrndactor |
$system.random.100 |
float - random number between 0.0 and 100.0 inclusive |
$system.none |
Form - none; i.e. a null Form |
$system.is_player.inside |
bool - is the Player currently in an interior location |
$system.is_player.outside |
bool - is the Player currently in an exterior location |
$system.is_player.in_city |
bool - is the Player currently in a City, Town, Habitation, or Dwelling |
$system.is_player.in_dungeon |
bool - is the Player currently in a DraugrCrypt, DragonPriestLair, FalmerHive, VampireLair, Dwarven Ruin, Dungeon, Mine, or Cave |
$system.is_player.in_safe |
bool - is the Player currently in a PlayerHome, Jail, or Inn |
$system.is_player.in_wilderness |
bool - is the Player currently in a Hold, BanditCamp, MilitaryFort, or a Location with no keyword |
$system.is_player.in_combat |
bool - true if the Player is currently in combat, false otherwise |
$system.stats.running_scripts |
int - current count of running scripts; will always be 1 or greater because you will be calling it from a script |
$system.realtime |
float - the current real time (i.e. seconds since launch of SkyrimSE.exe) from Utility.GetCurrentRealtime() |
$system.gametime |
float - the current game time (i.e. in-game days since your save was created) from Utility.GetCurrentGametime() |
$system.initialGameTime |
float - the game time when the script was started |
$system.initialScriptName |
string - the initial script that was requested; might differ from current script in case call was used |
$system.currentScriptName |
string - the current script that is running; might differ from current script in case call was used |
$system.sessionid |
int - the current SLTR sessionid (changes with each load of a save or creation of a new game) |
$system.forms.gold |
Form - returns the Form for gold (i.e. "0xf |
$system.forms.sltr_main |
Form - returns the SLTR Main Quest object (i.e. "0x83f |
$system.is_available.core |
bool - (Added by SLTR Core) is the SLTR Core extension available and enabled (very rare you would want this false) |
$system.toh_elapsed |
float - (Added by SLTR Core) actual elapsed time in hours since the previous top of the hour (may be larger than 1.0 if e.g. sleeping or traveling) |
$system.player.is_swimming |
bool - (Added by SLTR Core) true if player is swimming; false otherwise |
$system.player.is_in_water |
bool - (Added by SLTR Core) true if player is in water; false otherwise |
$system.player.submerged_level |
float - (Added by SLTR Core) current submerged level of player; 0.0 if not submerged/on dry land, 1.0 if fully submerged |
$system.player.swimming_start_gametime |
float - (Added by SLTR Core) gametime when player started current swim session; resets to 0.0 when not swimming |
$system.player.in_water_start_gametime |
float - (Added by SLTR Core) gametime when player started current in water session; resets to 0.0 when player leaves water |
$system.player.swimming_session |
int - (Added by SLTR Core) unique int ID to identify a period of unbroken time player spent swimming; 0 if not swimming |
$system.player.in_water_session |
int - (Added by SLTR Core) unique int ID to identify a period of unbroken time player spent in water; 0 if not in water |
$system.player.swimming_duration |
float - (Added by SLTR Core) gametime duration player has currently spent swimming; 0.0 if not currently swimming |
$system.player.in_water_duration |
float - (Added by SLTR Core) gametime duration player has currently spent in water; 0.0 if not currently in water |
$system.player.swimming_last_start_gametime |
float - (Added by SLTR Core) gametime when player started previous swim session |
$system.player.in_water_last_start_gametime |
float - (Added by SLTR Core) gametime when player started previous in water session |
$system.player.swimming_last_duration |
float - (Added by SLTR Core) gametime duration player was last swimming; might be very small for repeated re-entries of deep water |
$system.player.in_water_last_duration |
float - (Added by SLTR Core) gametime duration player was last in water; might be very small for repeated re-entries of shallow water |
$system.is_available.sexlab |
bool - (Added by SLTR SexLab) is the SLTR SexLab extension available and enabled (would be false if you installed on a system without SexLab) |
$system.partner |
Actor - (Added by SLTR SexLab) the first member of the target Actor's current SexLab scene that is not the target Actor |
$system.partner1 |
Actor - (Added by SLTR SexLab) the first member of the target Actor's current SexLab scene that is not the target Actor |
$system.partner2 |
Actor - (Added by SLTR SexLab) the second member of the target Actor's current SexLab scene that is not the target Actor |
$system.partner3 |
Actor - (Added by SLTR SexLab) the third member of the target Actor's current SexLab scene that is not the target Actor |
$system.partner4 |
Actor - (Added by SLTR SexLab) the fourth member of the target Actor's current SexLab scene that is not the target Actor |
$system.is_available.ostim |
bool - (Added by SLTR OStim) is the SLTR OStim extension available and enabled (would be false if you installed on a system without OStim) |
$system.ostim.partner |
Actor - (Added by SLTR OStim) the first member of the target Actor's current OStim scene that is not the target Actor |
$system.ostim.partner1 |
Actor - (Added by SLTR OStim) the first member of the target Actor's current OStim scene that is not the target Actor |
$system.ostim.partner2 |
Actor - (Added by SLTR OStim) the second member of the target Actor's current OStim scene that is not the target Actor |
$system.ostim.partner3 |
Actor - (Added by SLTR OStim) the third member of the target Actor's current OStim scene that is not the target Actor |
$system.ostim.partner4 |
Actor - (Added by SLTR OStim) the fourth member of the target Actor's current OStim scene that is not the target Actor |
request scoped variables are also read-only and typically intended to convey information relevant to the context of the trigger, or the environment at the time the script was requested. Unlike system scoped variables that are intrinsic to the system, request scoped variables are only going to have relevant information in certain circumstances.
| Variable | Returns |
|---|---|
$request.core.activatedContainer |
Form - (Added by SLTR Core) container that was activated as part of a container activation trigger |
$request.core.activatedContainer.is_corpse |
bool - (Added by SLTR Core) true if the activated container was a corpse |
$request.core.activatedContainer.is_empty |
bool - (Added by SLTR Core) true if the activated container was empty |
$request.core.activatedContainer.is_common |
bool - (Added by SLTR Core) true if the activated container is one of the 'Common' types |
$request.core.activatedContainer.count |
int - (Added by SLTR Core) returns the current count of inventory items in the activated container (yes, current; remove something and this value's result will change) |
$request.core.was_player.inside |
bool - (Added by SLTR Core) was the Player "Inside" at the time the trigger was handled |
$request.core.was_player.outside |
bool - (Added by SLTR Core) was the Player "Outside" at the time the trigger was handled |
$request.core.was_player.in_safe_area |
bool - (Added by SLTR Core) was the Player "In a Safe Area" at the time the trigger was handled |
$request.core.was_player.in_city |
bool - (Added by SLTR Core) was the Player "In a City" at the time the trigger was handled |
$request.core.was_player.in_wilderness |
bool - (Added by SLTR Core) was the Player "In the Wilderness" at the time the trigger was handled |
$request.core.was_player.in_dungeon |
bool - (Added by SLTR Core) was the Player "In a Dungeon" at the time the trigger was handled |
$request.core.from_location |
bool - (Added by SLTR Core) (for OnLocationChange) the Location travelled from; might be none/empty for many outdoor locations |
$request.core.to_location |
bool - (Added by SLTR Core) (for OnLocationChange) the Location travelled to; might be none/empty for many outdoor locations |
$request.core.equipped_item.base_form |
Form - (Added by SLTR Core) (for Player Equipment Change) the base Form for the item that was equipped/unequipped |
$request.core.equipped_item.object_reference |
ObjectReference - (Added by SLTR Core) (for Player Equipment Change) the ObjectReference from the original event; typically only available for unique items (e.g. artifacts) |
$request.core.equipped_item.is_equipping |
bool - (Added by SLTR Core) (for Player Equipment Change) true if the item was being equipped; false if the item was being unequipped |
$request.core.equipped_item.is_unique |
bool - (Added by SLTR Core) (for Player Equipment Change) true if the item was unique (event provided ObjectReference) ; false otherwise |
$request.core.equipped_item.has_enchantments |
bool - (Added by SLTR Core) (for Player Equipment Change) true if the item had enchantments; false otherwise |
$request.core.equipped_item.type |
string - (Added by SLTR Core) (for Player Equipment Change) One of 'Armor', 'Weapon', 'Spell', 'Potion', or 'Ammo' |
$request.core.player_on_hit.attacker |
Form - (Added by SLTR Core) (for Player On Hit) the Player if the Player was attacking, their opponent if the Player was being attacked |
$request.core.player_on_hit.target |
Form - (Added by SLTR Core) (for Player On Hit) the Player if the Player was being attacked, their opponent if the Player was attacking |
$request.core.player_on_hit.source |
int - (Added by SLTR Core) (for Player On Hit) the source FormID (weapon/spell) used for the attack |
$request.core.player_on_hit.projectile |
int - (Added by SLTR Core) (for Player On Hit) the projectile FormID used for the attack if one was involved |
$request.core.harvesting.harvested_item |
Form - (Added by SLTR Core) (for Harvesting) the Form item that was harvested e.g. 'Snowberries' |
$request.core.vampirism.was_contracted |
bool - (Added by SLTR Core) (for Vampirism Transitions) did you just contract it (i.e. disease progressed to Vampirism) |
$request.core.vampirism.was_cured |
bool - (Added by SLTR Core) (for Vampirism Transitions) were you cured? |
$request.core.vampirism.started_vampire_lord |
bool - (Added by SLTR Core) (for Vampirism Transitions) did you transform to Vampire Lord? |
$request.core.vampirism.ended_vampire_lord |
bool - (Added by SLTR Core) (for Vampirism Transitions) did you end the Vampire Lord transformation? |
$request.core.lycanthropy.was_contracted |
bool - (Added by SLTR Core) (for Lycanthropy Transitions) did you just contract it (e.g. Companions ceremony) |
$request.core.lycanthropy.was_cured |
bool - (Added by SLTR Core) (for Lycanthropy Transitions) were you cured? |
$request.core.lycanthropy.started_werewolf |
bool - (Added by SLTR Core) (for Lycanthropy Transitions) did you transform to Werewolf? |
$request.core.lycanthropy.ended_werewolf |
bool - (Added by SLTR Core) (for Lycanthropy Transitions) did you end the Werewolf transformation? |
$request.core.vampire_feeding.target |
Form - (Added by SLTR Core) (for Vampire Feeding) the target of the feeding |
$request.core.soul_trapped.trapper |
Form - (Added by SLTR Core) (for Soul Trapped) the trapper who trapped the target |
$request.core.soul_trapped.target |
Form - (Added by SLTR Core) (for Soul Trapped) the target that was trapped |
You can use the $"{$variablename}" construct to perform string interpolation. This will create a string literal with the specified variables injected into place. Scopes are respected, so you can also have references to e.g. global scoped variables.
set $global.monkey.count 21
set $var $"{$global.monkey.count} Monkeys"
; $var now contains '21 Monkeys'
Sets the value of the specified variable.
set $1 "Hi there"
msg_console $1
set $playerName "John"
msg_console $playerName
Sets a variable to the result of a function call.
set $playerName resultfrom actor_name $player
; $playerName now contains the player's name
Sets a variable to the result of an operation on two parameters.
- Operators:
+,-,*,/,&(string concatenation)
set $var1 3
set $var2 5
set $total $var1 + $var2
; $total now contains 8
Removes the key-value pair identified by the map-key argument.
set $mapvar{key} = "value"
mapunset $mapvar "key"
; $mapvar{key} no longer has a value
Returns true if a key-value pair identified by the map-key argument exists for this map.
set $mapvar{foo} = "value"
maphaskey $mapvar "foo"
; $$ is true
maphaskey $mapvar "bar"
; $$ is false
Copies all key-value pairs associated with the source map to the target map.
set $mapvar{key} = "value"
mapcopy $global.mapvar $mapvar
mapunset $mapvar "key"
; $mapvar{key} no longer has a value
; $global.mapvar{key} still has value "value"
Removes all key-value pairs associated with the map variable.
set $mapvar{key1} = "value1"
set $mapvar{key2} = "value2
mapclear $mapvar
; $mapvar{key1} and $mapvar{key2} no longer have a value
Returns a list of strings corresponding to the available keys in the map.
set $mapvar{fork} = "pointy"
set $mapvar{knife} = "cutty"
set $mapvar{spoon} = "scoopy"
set $keylist resultfrom mapkeys $mapvar
; $keylist now contains a list, ["fork", "knife", "spoon"]
Returns a count (the size) of the number of elements in the list.
set $listvar[0] = "first"
set $listvar[9] = "last"
set $count resultfrom listcount $listvar
; $count is 10, because by assigning to index 9, it resizes the 0-based list to accommodate
Adds the provided value(s) to the list, coercing it to the list's type as needed. listadd accepts more than 1 argument.
set $listvar[0] = "first"
; the list is a string list, because it's first indexed assignment is a string
listadd $listvar 27
; $listvar[1] is now "27", a string
set $intlist[0] = 100
; the list is an int list, because it's first indexed assignment is an int
listadd $intlist "two hundred"
; $intlist[1] is now 0, because "two hundred" as a string, cast to an int, returns 0
listclear
listadd $intlist 0 100 200 300 400
; $intlist[0-4] contain, respectively,the values indicated, i.e. the equivalent of $intlist[$i] = $i * 100
Removes all values from the list and sets its count/size to 0.
set $listvar[0] = "first"
set $listvar[1] = "second"
listclear $listvar
; $listvar[0] and $listvar[1] are no longer set and listcount will return 0
Sets the new size of the targeted list.
set $listvar[0] = "first"
set $listvar[1] = "second
listresize $listvar 1
; $listvar[1] is no longer set because the list was resized to hold only 1 element
; $listvar[0] remains unchanged
Copies a slice of data from a list, specified by a required slice length and an optional start index, which defaults to 0.
set $listvar[0] = "first"
set $listvar[1] = "second"
set $listvar[2] = "third"
set $listvar[3] = "fourth"
set $stringslice resultfrom listslice $listvar 2 1
; $stringslice is a list comprised of [ "second", "third" ]
The usage: listjoin $targetList $sourceList1 $sourceList2 ...
targetList: required
sourceList: 1 or more, must be list variables of the same type as the targetList
Form[] $theCrew
set $theCrew[0] = $system.player
set $theFollowers resultfrom nff_followers
listjoin $theCrew $theFollowers
; $theCrew contains the player and all NFF followers
Increments the numeric value of a variable by the specified amount (default: 1; float values like 2.3 are allowed).
set $2 12
inc $2 2
; $2 is now 14
inc $3 ; increments $3 by 1; since it was not set, it will be initialized to 0 and incremented by 1
Concatenates strings into the target variable.
cat $3 "one " "two " "three "
; $3 is now "one two three "
cat $4 $1 $2 $3
; $4 would have the contents of $1, $2, and $3, concatenated with no adjoining spaces
Returns the result from Game.GetCurrentCrosshairRef(), including Actors.
set $actor_under_cursor resultfrom cursor_ref
set $actor_name resultfrom actor_name $actor_under_cursor
msg_notify $actor_name
The type ID of a variable is an int value representing the underlying type when the variable was last assigned. Attempting to get the type ID of something that is not a variable, basically literals, will return 0. If a variable has not been set yet, it will return 0. This can be used to determine if a value has ever been set before, including globals. Because system variables are more akin to macros rather than actual variables, they also have no type ID. But you can obtain it by setting a variable to the value of the system variable.
Possible values:
- 0 - Invalid
- 1 - string
- 2 - bool
- 3 - int
- 4 - float
- 5 - Form (or Form sub-type e.g. ObjectReference, Actor)
- 6 - Label - a goto target e.g. [label]
- 7 - Map
- 8 - Alias (or ReferenceAlias)
- 101 - string[] (i.e. string list)
- 102 - bool[]
- 103 - int[]
- 104 - float[]
- 105 - Form[]
- 106 - Label[]
- ; there is no list of maps
- 108 - Alias[]
typeid $var
; $$ is 0
set $var "true"
typeid $var
; $$ is 1, because "true" is a string
set $var true
typeid $var
; $$ is 2, because the bare keyword true is a boolean
set $var 42
typeid $var
; $$ is 3
set $var 42.0
typeid $var
; $$ is 4
; $$ is 0 for all of the following literals
typeid "Hello, world!"
typeid 42
typeid true
typeid false
typeid 42.0
Returns the name associated with the id from typeid.
Possible values:
- "string"
- "int"
- "float"
- "bool"
- "Form"
- "Label"
- "Map"
- "Alias"
- "string[]"
- "bool[]"
- "int[]"
- "float[]"
- "Form[]"
- "Label[]"
- "Alias[]"
A [label] marks a line as a valid target for goto or if statements.
[done]
[mylabel]
Resets execution to begin on the line immediately following the indicated label.
set $1 "done"
goto below
set $1 "" ; this line is skipped
[done]
return
[below]
goto $1 ; jumps to 'done' label using variable
Performs a conditional check and redirects execution to a label if true.
Syntax:
; variant 1 - compare value1 and value 2
if <value1> <operator> <value2> <label>
; variant 2 - check value1 for "truthiness"
if <value1> <label>
Operators:
- Numeric:
=/==(equality),!=(inequality),>,>=,<,<= - String:
&=(equality),&!=(inequality)
set $2 12
set $3 12
if $2 > $3 gogt
if $2 < $3 golt
if $2 = $3 goeq
[goeq]
; execution continues here if $2 equals $3
Performs conditional checks and executes the commands in the block where the conditional check matches. else is the default.
Syntax:
; variant 1 - compare value1 and value 2
if <value1> <operator> <value2>
; variant 2 - check value1 for "truthiness"
if <value1>
; variant 1 - compare value1 and value 2
elseif <value1> <operator> <value2>
; variant 2 - check value1 for "truthiness"
elseif <value1>
; optional, default block if specified
else
; end of if-block
endif
Operators:
- Numeric:
=/==(equality),!=(inequality),>,>=,<,<= - String:
&=(equality),&!=(inequality)
set $zeroth 0
set $first 1
set $second 2
set $third 3
set $istrue true
if $first > $second
; won't execute because 1 < 2
elseif $zeroth
; won't execute because 0 is not "truthy"
elseif $istrue
; this will execute because true is "truthy"
elseif $first < $second
; won't execute becuse the if-block has already been satisfied
else
; won't execute becuse the if-block has already been satisfied
endif
Performs conditional checks and executes the commands in the block if the condition is true. Repeats the block until the condition is no longer true. WARNING: You must ensure you do something to make the condition false at some point, or return from the script, or else you will have an infinite loop.
Syntax:
; variant 1 - compare value1 and value 2
while <value1> <operator> <value2>
; variant 2 - check value1 for "truthiness"
while <value1>
; end of while-block, if the conditional is still true, execution will begin again at the top of the block
endwhile
Operators:
- Numeric:
=/==(equality),!=(inequality),>,>=,<,<= - String:
&=(equality),&!=(inequality)
set $counter 0
set $goal 10
while $counter < $goal
; this loop will iterate 10 times
msg_console $"Iteration {counter}"
inc $counter 1
endwhile
Exits the current SLTScript. If called from another script, execution returns to the calling script.
return
Subroutines allow you to create reusable blocks of code within your script.
beginsub dosomethingcomplex
; Your subroutine code here
; Shares the same variables as the main script
endsub
gosub dosomethingcomplex
; execution continues here after subroutine completes
Note: If execution flow reaches a beginsub during normal script execution, it will skip to the corresponding endsub.
; Main script flow
gosub dosomethingcomplex
; more code
gosub dosomethingcomplex
beginsub dosomethingcomplex
; Complex task code here
; This code can be called multiple times
endsub
Calls another SLTScript with its own variable scope (heap). Note that when referencing scripts you can leave off the .sltscript extension.
Syntax: call <script_name> [<arg1> <arg2> ...]
; ScriptA.sltscript
set $1 100
call "ScriptB" "some argument"
; $1 is still 100 - ScriptB's changes don't affect this script
In the called script, use callarg to access passed arguments.
Syntax: callarg <index> <variable>
; ScriptB.sltscript
callarg 0 $receivedArg
; $receivedArg now contains "some argument"
; ScriptA.sltscript
set $1 100
call "ScriptB"
if $1 >= 100 allgood
msg_notify "Something went wrong!"
return
[allgood]
msg_notify "All good!"
; ScriptB.sltscript
set $1 50 ; This doesn't affect ScriptA's $1
msg_notify "ScriptB executed successfully"
return
All commands beyond the intrinsics come from Function Libraries. SLTR includes an expanding library with functions covering not only base Skyrim but also SexLab, OStim, and other related mods.
For detailed information about available functions, see the Function Libraries wiki page.
- Use meaningful variable names to make your scripts more readable
- Comment your code using semicolons for complex logic
- Be cautious with long-running scripts due to the save/reload bug
- Test subroutines and script calls thoroughly to ensure proper variable scoping
JSON Format: JSON support has ended. Future development focuses on .sltscript format.
- Tokenization: Lines split on whitespace except within quotes or brackets
-
Escape sequences: Embedded double quotes use
"" - Variable resolution: Functions automatically determine expected data types for parameters
- Performance: Built-ins typically run faster than library functions but are less extensible