Syntax Reference

Script Block

A script is contained in a script block. This is equivalent to ScriptName extends... in Papyrus. The only thing that can go before a script block are comments and defines.

#define HELLO_WORLD

// The colon replaces the "extends"
script Demo : ObjectReference {}

States

A state is a block with a name and an optional auto flag.

See the CK Wiki State Documentation for more in-depth information

auto state DefaultState {
  // ...
}

state OtherState {
  // ...
}

Imports

Importing a script allows you to use its Global functions without having to prefix them with the script name.

See the CK Wiki Import Reference for more info

import Debug

def Demo() {
    // Without Import
    Debug.MessageBox("Hello World")
    
    // With Import
    MessageBox("Hello World")
}

Properties

A property is a script-scoped variable that's available to external scripts. A property itself does not actually store anything, it's an interface between a script's private variable and the outside world.

_player: Actor = None // a private variable

property Player: Actor {
    get {
        return _player
    }
    
    set {
        _player = value // value is a special variable that refers to the setter value
    }
}

Auto Properties

Auto properties represent a private variable and a basic setter like the one above. An auto property starts with auto property and then follows the regular variable format. They can optionally have a default value.

auto property PlayerREF: Actor
auto property Interval: Float = 1.0

Variables

Variable definitions begin with a name, followed by a type and finally an optional value. Since Papyrus doesn't do type inference, types must be explicitly defined. (Type inference is a future planned feature of PaperScript)

See the Papyrus Variable Reference for more details

If you don't specify a value, the variable will be filled with the Papyrus default for that type.

someBool: Bool = true
someInt: Int = 1

// Defaults
defaultBool: Bool // = false
defaultInt: Int // = 0
defaultFloat: Float // = 0.0
defaultString: String // = ""
defaultaRrray: Int[] // = None
someNullActor: Actor // = None

Functions

A function starts with def, has a name, optional arguments and an optional return type. Functions that don't have a return type (void), don't need to specify one.

def HelloWorld() {
  Debug.Notification("Hello World")
}

def ReturnsFloat() -> Float {
  return 1.0
}

def HasArgs(message: String) {
  Debug.Notification(message)
}

def ArgsAndReturn(a: Bool, b: Bool) -> Bool {
  return a | b
}

Events

Events work the same as functions but start with event instead of def and never have a return type.

event OnEquipped(actor: Actor) {}
event OnInit() {}

Conditionals

The If/ElseIf/Else syntax is virtually identical to Papyrus but with braces. Parentheses are optional and only used to denote precedence.

if a == b {
    // ...
} elseif a == c {
  // ...
} else {
  // ...
}

While

The while syntax is the same as Papyrus but with braces. Parentheses are once again optional and used for precedence.

while someCondition {
  // ...
}

Increment / Decrement

PaperScript has a simple implementation of the increment and decrement operators. It's basically just shorthand for adding or subtracting 1 from an int.

number: Int = 0

number++ // Equivalent to number += 1
number-- // Equivalent to number -= 1

Switch

A switch is one of the features sorely missing from Papyrus. PaperScript supports switch statements that get translated into if/elseif/else in the resulting Papyrus.

Cases can be single-line or multi-line. Single-line cases must end with a semicolon. Multi-line cases are in braces.

The default case follows the same pattern and will match anything that doesn't have a case.

Cases do not fall through and there is no break

switch someVar {
    case 1 => Debug.Notification("1");
    case 2 => {
      Debug.Notification("2")
    }
    default => Debug.Notification("default");
}

Range

range is another new addition to PaperScript that doesn't exist in Papyrus. It works as a foreach loop and gets translated into a while in the resulting Papyrus.

range item in items {
  DoSomething(item)
}

Array Initializers

This is a small quality of life improvement that makes a big difference. Initializing arrays with data is pretty annoying in Papyrus and PaperScript makes it a lot simpler.

arr1: Int[] = [ 1, 2, 3]

arr2: String[] = [
  "Hello",
  "World"
]

Struct Initializers

Just as with arrays, filling structs with data is kinda annoying in Papyrus as well. PaperScript simplifies this too.

point: Point = { x: 1, y: 2 }

fancyMessage: FancyMessage = { 
  title: "Title", 
  text: "Text", 
  color: "red", 
  bold: true 
}

Last updated