Control flow
Vellum gives you tools for controlling the flow of your scripts. Use an if statement, for and while loops to define your logic. For multi-way literal branches, see Pattern matching.
Conditional statements
You can use the if statement to branch your code logic depending on the condition specified in ():
script MyScript {
fun Foo() {
Bar(42)
}
fun Bar(i: Int) {
if i < 100 {
Baz()
} else if i == 100 {
Qux()
} else {
// do nothing
}
}
fun Baz() {
}
fun Qux() {
}
}
Objects, numbers, strings, and arrays are implicitly cast to Bool (see Casts):
script MyScript : ObjectReference {
event OnActivate(obj: ObjectReference) {
var actor = obj as Actor
if !actor {
return
}
if actor {
// actor is non-none
}
}
}
Vellum supports the conditional ternary operator ?: that you can use, for example, for conditional variable initialization:
script MyScript {
fun Foo() {
Bar(true)
}
fun Bar(condition: Bool) {
var i = condition ? 42 : -1
}
}
Loops
Use a while loop for loops with arbitrary condition:
script MyScript {
fun Foo() {
var i = 0
while i < 10 {
i += 1
}
}
}
Use a for loop to iterate over an array or a FormList:
script MyScript {
fun Foo(nums: [Int]) {
// iterate over array of numbers
for num in nums {
// do something with num
}
}
fun Bar(items: FormList) {
// FormList elements are Form
for item in items {
// do something with item
}
}
}
Optionally bind the zero-based index after the value name:
script MyScript {
fun SumIndexed(nums: [Int]) -> Int {
var total = 0
for num, i in nums {
total += num
// i is Int (0, 1, 2, ...)
}
return total
}
fun WalkParallel(recipes: FormList, results: FormList) {
for recipe, i in recipes {
var result = results.GetAt(i)
// ...
}
}
}
Int ranges use exclusive ... Ascending and descending (countdown) are both supported:
script MyScript {
fun CountUp(n: Int) {
// 0, 1, ..., n-1
for i in 0..n {
// ...
}
}
fun CountDown(n: Int) {
// n, n-1, ..., 1 (excludes 0)
for i in n..0 {
// ...
}
}
}
Equal bounds (5..5) produce no iterations. Index bindings (for x, i in …) are only for arrays and FormLists, not ranges.
Jump statements
You can use a return statement for early returning from a function:
script MyScript : ObjectReference {
event OnActivate(obj: ObjectReference) {
if obj != Game.GetPlayer() {
return
}
// do something
}
}
Inside loops you can use break and continue statements.
breakterminates the nearest enclosing loopcontinueproceeds to the next step of the nearest enclosing loop
script MyScript : ObjectReference {
fun Foo() {
var i = 0
while true {
if i == 10 {
break
}
i += 1
}
}
fun Bar(actors: [Actor]) {
// process array of actors
for actor in actors {
// skip none objects
if actor == none {
continue
}
// do something with valid actor
}
}
}