SUNRISE STUDIO

Script a mission

The Mission Graph edits mission scripts: the Lua files Sunrise runs while an activity is live. It shows a script as a node graph and as Lua. Mission Scripting explains what a script is and how it runs.

Mission scripts are plain Lua files, not package data. They are never stored as deltas.

scriptlives insave writes
installed scriptbin/x64/Sunrise/scripts/<stem>/<stem>.luathat file, in place; no project needed
mod scriptthe project’s scripts/<stem>/<stem>.luathe project file; needs its project open

Open the Mission Graph

  1. Choose View > Mission Graph.

It opens in its own area of the layout, or in its own window when it is popped out. See Arrange the layout. To open a script, choose it in Installed scripts, or in Mod scripts with a project open.

The toolbar holds these controls. Icon buttons name themselves in their tooltip.

controldoes
+ (New script)starts a new script
Installed scriptsopens an installed script; its tooltip shows the open script’s file
circular arrow (Reload scripts and API schema)reads the scripts and the SDK again
Mod scriptsopens a script of the open project
Savesaves the script; it shows Save* while there are unsaved changes
export (Export Lua for review)writes a copy to a folder outside the installation
Read onlyshows when the script’s project is not open for editing
warning iconshows when there is no API schema; its tooltip says why
forward arrow (Finish switching scripts)shows while a switch waits on unsaved changes; opens its dialog again

Press reload after the game or a git pull changes the scripts or the SDK. Undo and redo are in the Edit menu.

Create a new script

  1. Press + (New script), or choose File > New mission script….
  2. In Activity, search for and choose an activity from the installed SDK.
  3. In Arrival region, choose the region where the script starts.
  4. Check Graph key. It defaults to the script’s name.
  5. Under Save to, choose Installed scripts or This project (mod).
  6. Press Create script.

The activity sets the folder and file name, so a place holds one script per activity. Create refuses a script that already exists. Open that one instead. A new script targets an existing activity. It does not create a new activity.

The dialog names any SDK file that is missing or damaged. Start the game once to rebuild it. When scripts/lib/flow.lua is missing, the dialog says so and Create script stays off.

The starter script waits until the player enters the arrival region, then runs its first step. It resumes saved progress on load. It does not complete the mission on its own.

Add a step

  1. Open the Nodes tab.
  2. Select the facts group or the steps group.
  3. Press + (Add node).
  4. Type a Node id.
  5. Choose a Template.
  6. Choose the Sensor, Target, Navpoint, Scene, Input, Output or Inputs the template asks for.
  7. Press Create.
templategroupdoes
Observe triggerfactswaits for a player-trigger report, then disarms the trigger
Scene outputfactswaits until a scene reports one of its outputs
Immediate stepstepsstarts with an empty action
Arm triggerstepsarms an SDK trigger slot
Show objectivestepssets a directive on its sensor, with an optional navpoint
Play dialoguestepsplays a cue on its dialogue sensor
Select statestepsselects an SDK state
Complete missionstepscompletes the mission
Start scenestepsstarts a scene, then sends the inputs you tick, in the order you tick them
Send scene inputstepssends one input to a scene

In a campaign graph, the steps group offers other templates: Immediate step, Reach trigger, Complete ghost scan and Use interactable.

Scene inputs and outputs

A scene is a scripted piece of a mission, such as an explosion or a character’s performance. Each scene has its own inputs and outputs.

  • An input is an event the scene waits for. A script sends it.
  • An output is an event the scene reports. A script waits for it.

Pickers only offer the inputs and outputs of the scene you chose. They come from the installed SDK’s mission.SceneInput and mission.SceneOutput tables. An SDK generated before these tables existed lists none. Start the game once with the current Sunrise to regenerate it, then press reload on the toolbar. See Generated SDK and The world model.

A Scene output fact needs the script to pass scene outputs to its flow. New scripts do this. For an older script, add on_event_scene_output to the table it returns, the same way as its other on_event_ callbacks. Until then, Checks reports the fact.

Campaign steps

Campaign steps run in list order. Select a step and press the up or down arrow (Move before the previous node, Move after the next node) to move it. Links between campaign steps show that order and cannot be dragged.

Select a step to edit its fields:

fielddoes
Objective, Navpoint, Waypoint volumewhat the step shows the player
Start scenestarts this scene when the step starts
Inputssends the ticked inputs right after the scene starts; needs a start scene
Arm in leg, Triggerends the step on that trigger; the leg arms it
Ghost scan, Interactionends the step on that scan or interaction
Scene finishedends the step when that scene finishes
Output scene, Scene outputends the step when that scene reports that output after the step started
Encounter cleared, Region reachedends the step on that encounter or leg
Barriera later step’s trigger cannot end this step early
Revisitthe step’s trigger and region count only after the step starts
Dialoguecue lines, each with an optional filter volume

A step with no end condition completes at once. The inspector then shows Completes immediately.

Choosing another start scene drops inputs that belong to the old one. Clearing it drops all inputs. Choosing another output scene clears the output until you pick a new one.

Select a leg to set its State. Edit its trigger and monitor lists in Advanced Lua.

Encounter nodes and a step’s destroyed-object list have no typed fields. Edit them in Advanced Lua.

Make a step wait for another

This works for flow steps only. Campaign steps run in list order.

  1. Drag from the first step’s output arrow, on its right, to the second step’s input ring, on its left.

The second step then runs after the first finishes. The Dependencies checkboxes of a selected step set the same links.

To remove a link, do one of these:

  • Click it and press Disconnect.
  • Right-click it and choose Disconnect.
  • Drag it off its input ring onto empty space.

Dropping a link on an invalid target keeps the old link.

Edit a step’s action

Flow steps only.

  1. Select the step.
  2. Under Action, press Edit action.
  3. Choose the Action type and fill its fields.
  4. Press Apply.

Set when a step starts and finishes

Flow steps only.

  1. Select the step.
  2. In Start when, choose Immediately, Fact, All or Any.
  3. In Finish when, choose the same way.
  4. For All or Any, press Add condition for each child condition.
conditionmeans
Immediatelyno condition
Facta named fact in this flow is set
Allevery child condition holds
Anyat least one child condition holds

All and Any do not pick one branch: every eligible step can run. Facts stay set for the attempt unless a checkpoint resets them. Tick Checkpoint on a step to make it one.

Edit Lua directly

A Lua box opens as a preview. Press Edit to type in it, and Preview to go back.

whereapplydrop the edit
a Custom Lua field, or a node written as LuaApplyRevert
the Lua section of a typed action or conditionApplyRevert
Code or Advanced Lua on a script-view nodeApplyRevert
Inputs of a script-view nodeApplyRevert
Advanced Lua on a flow or campaign nodeApplyselect the field again
the Lua tabApplyRevert

Script-view inputs and the flow or campaign Advanced Lua box have no preview. In Advanced Lua, pick a field from the list or type its path, then edit the box.

Unapplied Lua marks the script as unsaved.

  • A pending field edit blocks Save, Undo, Redo, Export and other edits. Apply or revert it first.
  • Save, Export and graph edits apply a pending Lua tab edit first. Undo drops it, and Redo brings it back.
  • While a Lua tab edit is pending, the Script group is read only and no field edit applies. Redo is refused until you revert it.

Studio reads Lua 5.4 and refuses any edit that leaves a syntax error. On the Lua tab, the error names its line and column, and the draft stays so you can fix it. A script file with a syntax error does not open; fix it in a text editor first.

Save

  1. Press Save, or press Ctrl+S while the Mission Graph has focus.

An installed script saves in place. A mod script saves into the project. The export button (Export Lua for review) writes a copy for review to a folder outside the installation. Node positions are kept in your local settings, per script.

When you switch scripts, projects or installations with unsaved changes, the Unsaved mission script dialog asks you to Save and continue, Discard or Cancel. After Cancel, the switch waits. Press the forward arrow (Finish switching scripts) on the toolbar to choose again. Saving also finishes the switch.

Check the script

  1. Open the Checks tab. Its title shows the number of problems.

It lists graph errors, such as unknown dependencies or facts, cycles, invalid conditions, duplicate ids and over-long state keys. It also lists scene errors:

  • an input sent to a scene that does not have it
  • an output waited for on a scene that does not report it
  • a campaign step with inputs but no start scene
  • a campaign step whose scene is a slot, not a mission.Scene entry
  • an input or output name that the installed SDK does not list
  • a scene output fact in a script with no on_event_scene_output callback

It also names a missing or damaged SDK file, and lists the problems of typed calls. See Checks on typed calls. With nothing to report, it says No problems found. With no API schema, it also says that API calls were not checked.

Graph errors block Export Lua for review, Build and install and Update running game. They do not block Save. Scene and call problems block nothing.

It is not a Lua compiler, and a passing check does not prove the mission plays in game.

Run it in the game

  • An installed script runs the next time its activity starts. In game, the Script page’s Reload script loads it again. See Your first script.
  • A mod script needs Build > Build and install while the game is closed.
  • While the game runs, Build > Update running game reloads changed mod scripts. See Build and install a mod.

The whole-script view

The Script group shows the whole Lua file as a graph. Every top-level statement is a node, and so is every field of the returned callback table. A link runs from the node that defines a name to each node that uses it. A module node shows its local name, with its require line below.

controleffect
double-click a function or callbackopens its control flow
folder (Open the body), forward arrow (Open the flow)open the selected node’s body or flow
folder on a flow or campaign node (Open run, for example)opens that field’s function
back arrow (Up to script)returns to the whole-script view
corners (Frame all)fits the group in view
grid (Arrange as a tree)lays the group out again as a tree
up and down arrowsmove the node within its scope
trash can (Remove node)removes the node
+ (Add node)adds a function, value, callback or statement
+ next to a body or branch name, under Add insideadds a statement or an API call there
Add else if, Add else, under Branchesadds a branch to an if node

A group opens framed, but text never shrinks too small to read. A long chain wraps to the width of the canvas. Pan or zoom out to see a graph that is still wider.

To add a function or a value, type its name in the Name box of the Add node popup, then choose Function or Value.

If, else-if, else, while, for, repeat, local scopes, calls, assignments, returns and breaks have their own nodes. Code the graph cannot show as nodes stays a Custom Lua block, and the inspector says why. Its neighbors still show as nodes. Edits replace only their own source and keep comments and line endings.

Typed API nodes

A statement that is one Sunrise API call is a typed node. Its arguments are fields you edit, not Lua text. A call inside a larger statement, such as an if condition, gets the same editor in that statement’s inspector. The statement’s own call is open. Other calls fold under their own Call headers. Calls the schema cannot describe stay Custom Lua blocks, so every script still opens and edits in full.

The types come from the generated SDK file sdk/lua/sunrise/mission_api.json. Sunrise writes it from the same table the runtime uses to check arguments. See Generated SDK. An installation that has not written it yet shows every call as Lua, and the toolbar shows a warning icon. Start the game once with the current Sunrise, then press reload on the toolbar.

How a call is typed

Studio types parameters named context, state and event, and the handles their calls return. A Sunrise API call it cannot type stays a Custom Lua block, and the inspector says why. Any other call is a call node with Call and Arguments inputs.

Edit a typed call

  1. Select the node. Under Call, each argument has a row. A * marks a required argument.
  2. Change a value. The edit replaces only that value in the source.

A text or number field applies when you press Enter or leave the field.

argument kindeditor
booleancheckbox
integer, numbernumber field, kept inside the allowed range
string, nametext field
scalar (boolean, number or string)text field; type the Lua value, such as true, 3 or "name"
enum, such as a device transitionlist of the collection’s entries
generated entry, such as a directive or a scene inputpicker of the installed SDK’s entries
slot, squad or scene handlepicker of the entries that match the slot type
listone row per entry
tableone row per field
atom of run_atomsits kind, then the fields of that kind
functionLua

A picker offers only what the schema allows. A slot picker lists slots of the slot type the call needs. A scoped picker lists the receiver’s own entries, such as the inputs of that scene.

buttoneffect
Luaedits the value as Lua; it stays lit while on, and pressing it again goes back
+ on an absent argumentadds it with its default or a valid placeholder
+ (Add entry) under a listadds a list entry, up to the allowed count
trash canremoves an optional argument or a list entry

In Lua mode the box is open for typing at once. Press Apply to apply it, or Revert to drop it. An absent optional argument shows its default, greyed out.

A value that is not a literal or a generated entry, such as a local, opens as Lua.

Adding keeps the table’s style: one line or one field per line, and a trailing comma only where the table has one.

A call that passes a table built in Lua, such as squad:place(args), shows no argument rows. Edit it in Advanced Lua.

Checks on typed calls

Studio checks literal values the way the runtime does. It finds problems such as:

  • the wrong call form: : where . belongs, or the wrong number of arguments
  • a required argument that is missing, or a key the call does not take
  • a value of the wrong type, such as text where a number belongs
  • a number outside its range, or a string of the wrong length
  • a list with too few or too many entries
  • an entry that is not in the installed SDK, or that comes from another table
  • a slot of the wrong slot type, or an entry that belongs to another slot or scene
  • an atom with no kind, or a field its kind does not have

A problem shows on the node, in its inspector and on the Checks tab. It blocks nothing. Code the checks cannot read, such as a value computed at run time, is not checked.

Add a callback or a call

  1. On the script view, press + (Add node). Under Callbacks, choose one. It is added to the returned table with the parameters the runtime passes. A callback the script already returns is greyed out.
  2. In a function, press a + under Add inside. Choose a statement, such as If or While, or a call under Sunrise API.

The list holds the calls that a value in scope can make, such as context and what it reaches. A call that needs a slot type the mission does not have is not listed.

A new call has a placeholder for each required argument. The placeholder is valid: the default, the first matching SDK entry, or zero moved into the allowed range. Change it before you save. A callback node shows the fields its event carries.

Helpers and SDK modules

fileexample path in the projectloaded with
helper modulescripts/lib/tools.luarequire("lib.tools")
own SDK modulesdk/my_mod/bindings.luarequire("my_mod.bindings")

Folder and module names use ASCII letters, digits and underscores. A controller must fit 128 KiB. Other modules can be up to 16 MiB. Edit helpers in a text editor. The Mission Graph lists controllers. Studio does not copy the generated SDK into projects.

Legacy scripts

Mod scripts lists a project’s .sunrise-mission.json scripts under Legacy scripts. Open one and save it to create its Lua file. To get its exact source, right-click the entry and choose Export original Lua.