Overview
Vellum is a scripting language created for the Creation Kit. Vellum keeps compatibility with the Papyrus ecosystem and offers clearer syntax and tooling.
For now, only the Skyrim PEX subset is supported. Support for Fallout 4 and Starfield is planned.
Vellum is case-sensitive. Prefer PascalCase for fun and event names (OnActivate, CountItems). When you override Papyrus parents, matching is still case-insensitive for compatibility.
Script declaration
See Inheritance for extending base scripts and script attachment.
Put your script inside a .vel file. Classic hello world example in Vellum:
import Debug
script HelloWorld : ObjectReference {
event OnActivate(actionRef: ObjectReference) {
MessageBox("Hello, World!")
}
}
Functions and events
See Functions.
You can define a function using the fun keyword. A function that takes two Int parameters and returns an Int:
fun Sum(a: Int, b: Int) -> Int {
return a + b
}
Event definitions start with the event keyword:
event OnActivate(activator: ObjectReference) {
PlayAnimation("CoolStuff")
}
Imports
See Imports.
import Debug
script MyScript {
fun Foo() {
Notification("bare static call")
}
}
Variables
See Variables.
In Vellum, you declare a variable using the var keyword followed by the name of the variable:
var x: Int = 4
var m: String = "Hello"
Vellum supports type inference, so you can omit the type after the variable name:
var x = 4 // type `Int` is inferred
Properties
See Properties.
Properties are defined using the var keyword followed by name, type, and accessors:
var myProperty: String {get set} // defines auto property myProperty with type String
var anotherProperty: Float {get} // defines readonly property anotherProperty with type Float
Strings
See Strings.
var name = "Vellum"
Debug.Notification($"Hello, {name}")
Arrays
See Arrays.
Arrays can hold multiple items of the same type:
var numbers = [Int; 10] // defines array of 10 Ints
numbers[0] = 5 // assign 5 to the first element of array numbers
var x = numbers[9] // assign array last element value to new variable x
You can use the length property to get the number of elements:
var numbersCount = numbers.length
Initializer lists work too: var nums = [1, 2, 3, 4].
For loop
See Control flow.
Use a for loop to iterate over an array:
var messages = [String; 5] // array of 5 String objects
// fill messages array somehow
// ...
// ...
for message in messages {
ProcessMessage(message)
}
You can also iterate FormLists, bind an index (for x, i in …), or loop over an Int range (for i in 0..n).
While loop
See Control flow.
A while loop runs the code inside the loop body continuously while the condition is satisfied:
var x = 0
while x < 10 {
x += 1
}
You can use break and continue statements to control the flow of loops (like for and while).
If statement
See Control flow.
// assume value is set
var x: Int
if value > 10 {
x = 1
} else {
x = 0
}
Pattern matching
See Pattern matching.
match kind {
1 | 2 => return "blade"
else => return "other"
}
Ternary conditional operator
See Control flow.
In some cases you can shorten your if statement:
// assume value is set
var x = value > 10 ? 1 : 0
You can also use it in a return statement:
fun Max(a: Int, b: Int) -> Int {
return a > b ? a : b
}
States
See States.
script MyScript {
}
state MyState {
event OnInit() {
}
fun Foo() {
}
}
If you want your script to start in a particular state, put the auto keyword before state:
script MyScript {
}
auto state InitialState {
}
Casts
See Casts.
Write expression as Type to convert when allowed (for example obj as Actor). Use expression is Type for a Bool type test.
Modifiers
See Modifiers for hidden / conditional on scripts, properties, and variables.