Scenario Authoring Guide
A guide to author better VR scenarios
This document is a reference for trainers creating scenarios in FacilityVR. It covers scenario configuration, equipment interaction, and advanced features.
Note: The facility layout and equipment reference sections below use the datacenter as an example. The same principles apply to all facility types (warehouse, oil rig, offshore, wind turbine, etc.). Each facility type has its own equipment with unique hotspots — use the dashboard’s equipment dropdowns to see available interactions for your layout.
New Features
Produce Mode Scenarios
Produce scenarios flip the model: instead of giving the trainee a fully-built layout to walk through, you give them a layout to build themselves. Their placements are graded against rule primitives you author. Each student gets their own per-attempt clone of the layout — their work never touches the original.
Use this when you want to assess design skills, not just procedure-following: “rack two production servers with redundant PDUs”, “lay out fire safety signage for this floor plan”, “wire the power chain from junction box to rack PDUs”, and so on.
Authoring a Produce scenario
- Create a new scenario, set Scenario Type to Produce (student constructs layout) at the top of Basic Information.
- Pick the facility layout the student will fork. Each attempt gets a clone of this layout — items the student places never affect the original.
- The Pre-Conditions, State Reactions, Scenario Equipment, and Cooperative sections are hidden because they don’t apply to Produce mode. (Equipment initial state and reactions live on the layout itself for Produce mode — author them in the in-VR layout editor.)
- Add one or more Steps. Each step has a title, description, and a set of rules that grade the student’s clone.
- Pick a Pass mode for each step:
- All rules must pass — every rule has to come back green.
- At least N rules pass — set the threshold below; useful for “do any 3 of these 5”.
- Weighted score ≥ threshold — each rule gets a
weight; passes ifsum(passed weights) / sum(all weights) ≥ threshold.
- Save and publish as you would any scenario.
Produce rule primitives
| Primitive | What it checks | Example |
|---|---|---|
item_count | Count placements matching a filter, assert min/max | At least 2 server racks placed |
spatial | Every subject within (or none within) a distance of a target | Every rack within 5 m of a CRAH unit |
coverage | Every subject is covered by at least one nearby target | Every aisle has a smoke detector overhead |
spacing | Minimum pairwise distance between matching items | No two racks closer than 1.2 m |
connectivity | A and B are linked by a connector decoration | PDUs cabled to racks |
sequence | A connector path walks expected items in order | Power flow: junction box → switchboard → UPS → PDU → rack PDU |
Filters in every primitive can match by equipment type, decoration type, tag on the placement, space, and (for signs) sign type. The dashboard’s rule editor pulls the equipment-type and space dropdowns from your selected layout — typing also works for tags or types you haven’t placed yet. When decoration type is set to sign, an extra Sign type picker appears, populated with all ISO-categorised safety signs so you can require a specific sign per space (e.g. fire_extinguisher in the kitchen, emergency_exit in the corridor).
Connector primitives (connectivity, sequence) look for connector-style decorations placed in the layout. Pick the style (cable, pipe, conduit, etc.) the student must use; tolerance defines how close (in metres) a connector vertex must be to an equipment item to count as touching it (default 0.5 m). Sequence has two modes: any (one path satisfies the order — “demonstrate flow to any rack PDU”) or each (every terminal item is reached by some sequence-matching path — “supply power to every rack PDU”).
Worked examples for every primitive — including one-rule-per-space patterns, weighted/mandatory mixes, and common pitfalls — live in the Build-Rules Cookbook.
Assigning a Produce scenario
Same flow as Perform scenarios: assign to a trainee or attach the scenario to a course step. On the assignment detail page, Produce scenarios show an Attempts panel instead of the usual Launch button:
- Trainee clicks Open Editor → backend forks the layout into a clone owned by them → the 3D Designer opens in a browser tab.
- Trainee builds, can Reset in practice mode (assessment mode is trainer-only reset), and clicks Submit when done.
- Submit locks the clone, runs the rules server-side, and pops a result modal with per-step pass/fail and the overall score.
- In-editor Start Assessment — assignments created in practice mode show a yellow Start Assessment button in the editor toolbar. Clicking it flips the assignment to assessment mode and resets the clone (the current practice attempt is marked abandoned and a fresh clone is forked) so the trainee can’t carry practice progress into the graded attempt. The switch is one-way.
- Trainer sees every attempt in the panel with status + score and can open any attempt read-only.
- Trainer can Re-evaluate a submitted attempt without unlocking — pick snapshot (rules-as-submitted) or current (whatever the rules say today, overwrites the score).
In-editor experience for the trainee
Produce exercises run in the browser — same desktop editor that trainers use to author layouts (mouse + WASD navigation). VR headsets are only used for Perform scenarios; the editor’s HTML overlay (sidebar pickers, step panel) doesn’t have a VR equivalent yet. The Produce-mode editor keeps the same placement controls as the layout editor but adds:
- A left-side step panel listing every step with a live status indicator (green ✓ / red ✗ / grey). Click a step to expand it and see per-rule detail — the rule lines explain why a rule passed or failed (e.g. “Found 1 server_rack, expected 2-3”).
- 3D failing-subject highlights — when a step is expanded, every failing item in that step gets a pulsing red ring on the floor and a bobbing arrow above it. Visible through walls so the student can find offenders fast.
- A Submit button in the toolbar. Submit warns if there are unsaved changes and asks for confirmation since it’s irreversible.
After submit, the editor reloads in read-only mode — pickers are hidden, the banner reads “submitted”, and the student (and trainer) can still walk through the layout and inspect what was graded.
Walking the build in VR
The student’s most-recent Produce attempt for each scenario also appears in their VR headset’s lobby under a My Attempts section. They can put on a headset and walk through what they built (or what they’re still building). Other students don’t see each other’s clones — that’s a Phase 3 sharing feature. Trainers don’t see student clones in the lobby either; review happens via the dashboard’s Attempts panel.
Self-paced students in courses
Course modules can include scenario steps. When a self-paced student reaches a Produce-scenario step, the course-learn page shows the same Attempts panel — no trainer push needed. The assignment is materialised on demand; subsequent visits resume the in-progress clone.
Scenario Equipment (Temporary Items)
Scenarios can now add temporary equipment to a layout that only appears during that scenario. This enables:
- Pick & pack training — place cartons with specific barcodes on racking shelves
- Assembly training — place ingredients or components on a work surface
- Inspection scenarios — place items that need to be found and checked
Configure in the Scenario Equipment section of the scenario form:
- Select the target space (room) in the layout
- Choose an equipment type (e.g.
carton,pallet) - Set a unique ID and label
- Set the position (x, y, z) within the space
- Use pre-conditions to set initial values (e.g. barcode numbers)
- Use Equipment Move task steps to validate pick-and-place actions
Temporary items are removed when the scenario ends.
Animated Equipment Parts
Equipment can have parts that move in response to interactions:
| Equipment | Interaction | Animation |
|---|---|---|
| Counterbalance forklift | Pull lift lever | Forks rise/lower smoothly |
| Reach truck | Pull lift lever | Fork carriage moves up/down mast |
| Pallet jack | Pump handle | Forks rise slightly |
Animations are state-driven — use state reactions to chain them (e.g. pressing a button triggers a valve animation).
Custom equipment created by the AI can also have animated parts using stateBinding.transforms on procedural geometry parts.
Equipment Labels
Floating text labels above equipment can be controlled:
- Per layout — toggle on the facility detail page Settings card
- Assessment mode — automatically hidden
- Hints disabled — automatically hidden
Template Scenario Bundling
When publishing a layout as a template, you can select scenarios to bundle with it. When another user forks the template, they can choose to import the bundled scenarios as drafts linked to their new layout.
Facility Layout (Demo Data Center Example)
+Z (south)
VESTIBULE
(entry — white/grey zone transition)
|
vestibule corridor
|
COOLING ROOM POWER ROOM
2× CRAH units 2× UPS
| 4× PDU
+--- west corridor ---+--- east corridor ---+
|
MAIN DATA HALL
12× Server Racks (rows A+B)
8× Raised Floor Tiles
1× EPO Button (south wall, near exit)
|
CONTROL ROOM
4× Patch Panels
1× Crash Cart
1× Fire Suppression Panel
3× Control Room Screens
GENERATOR YARD (outdoor)
2× Diesel Generators
2× Fuel Tanks
2× Fuel Pipes (with shutoff valves)
1× Fire Extinguisher
|
yard access corridor
|
COOLING ROOM (north door)
-Z (north)
Equipment Reference
Server Rack
Location: Main Data Hall — 12 units in two rows (A1–A6, B1–B6)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
rack-A1 … rack-B6 | LED indicator | status | "ok" (green), "warning" (amber), "failed" (red) |
rack-A1 … rack-B6 | Display label | value | Any text (e.g. "A1 — DEGRADED") |
rack-A1-door … rack-B6-door | Toggleable — click to open/close | — | Front door swings open |
rack-A1-drive1 … drive4 | Grabbable — click to remove/insert | — | Hot-swap drive bay |
rack-A1-drive1 … drive4 | LED indicator | status | "ok" (green), "warning" (amber), "failed" (red) |
Each rack has 4 drive bays (drive1–drive4) and a front door.
PDU (Power Distribution Unit)
Location: Power Room — 4 units (pdu-1, pdu-2, pdu-3, pdu-4)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
pdu-1 | Display label | load | Any text (e.g. "45%", "OVERLOAD") |
pdu-1-switch1 … switch6 | Pressable — click to toggle | on | true / false |
pdu-1-switch1 … switch6 | LED indicator | on | Mirrors switch state |
pdu-1-main | Pressable — main breaker | on | true / false |
Each PDU has 6 individual breaker switches and 1 main power switch.
CRAH Unit (Computer Room Air Handler)
Location: Cooling Room — 2 units (crah-1, crah-2)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
crah-1 | Display label | temp | Temperature text (e.g. "22", "28") |
crah-1 | Display label | supply-temp | Supply temperature (e.g. "18") |
crah-1 | Display label | value | General display text |
crah-1 | LED indicator | running | true (green) / false (off) |
crah-1 | LED indicator | filterDirty | true (amber) / false (off) |
crah-1 | LED indicator | status | "ok" (green), "warning" (amber), "failed" (red) |
crah-1-filter | Toggleable — click to open/close | — | Opens filter access panel |
UPS (Uninterruptible Power Supply)
Location: Power Room — 2 units (ups-1, ups-2)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
ups-1 | Display label | batteryLevel | Text (e.g. "100%", "15%") |
ups-1 | LED indicator | status | "ok" (green), "warning" (amber), "failed" (red) |
ups-1 | LED indicator | charging | true (amber) / false (off) |
Fire Suppression Panel
Location: Control Room — 1 unit (fire-panel)
The fire suppression panel is located in the control room, a secure and monitored location.
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
fire-panel-cover | Toggleable — click to open/close | — | Opens panel cover |
fire-panel | Pressable — activation button | activated | true (activates suppression) |
fire-panel | LED indicator | armed | true (green) / false (off) |
fire-panel | LED indicator | activated | true (red) / false (off) |
fire-panel | LED indicator | status | "ok", "warning" |
EPO Button (Emergency Power Off)
Location: Main Data Hall — south wall near the exit to the vestibule — 1 unit (epo-button)
The EPO button is positioned next to the evacuation route for quick access during emergencies.
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
epo-button-cover | Toggleable — click to lift safety cover | — | Lifts/lowers cover |
epo-button | Pressable — mushroom button | pressed | true (cuts all power) |
Floor Tiles (Raised Floor)
Location: Main Data Hall — 8 tiles between rack rows
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
tile-hall--6 | Toggleable — click to lift | lifted | Slides tile to reveal sub-floor |
tile-hall--4.5 | " | " | " |
tile-hall--3 | " | " | " |
tile-hall--1.5 | " | " | " |
tile-hall-0 | " | " | " |
tile-hall-1.5 | " | " | " |
tile-hall-3 | " | " | " |
tile-hall-4.5 | " | " | " |
Patch Panel
Location: Control Room — 4 units (patch-1, patch-2, patch-3, patch-4)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
patch-1-port1 … port32 | LED indicator | connected | true (green) / false (off) |
Each panel has 32 ports (8 columns × 4 rows). Ports are numbered left-to-right, top-to-bottom.
Crash Cart
Location: Control Room — 1 unit (kvm-cart)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
kvm-cart | Grabbable — click to reposition | — | Move cart to a rack |
kvm-cart | Display label | display | Screen text (e.g. "KVM READY", "CONNECTED TO A3") |
Control Room Screen
Location: Control Room — 3 screens mounted on the north wall (screen-power, screen-env, screen-alarms)
Control room screens display real-time equipment status. In cooperative mode, the operator uses these screens to monitor the facility and raise tickets.
| Object ID | Label | Monitored Equipment |
|---|---|---|
screen-power | Power | pdu-A1, pdu-A2, ups-1, epo-main |
screen-env | Environmental | crah-1, crah-2, crah-3, crah-4 |
screen-alarms | Alarms | fire-panel, epo-main, ups-1 |
Diesel Generator
Location: Generator Yard — 2 units (gen-1, gen-2)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
gen-1 | Toggle switch | on | true (running) / false (off) |
gen-1 | LED indicator (status) | status | "ok" (green), "warning" (amber), "failed" (red) |
gen-1 | LED indicator (fuel connection) | fuelConnected | true (green) / false (off) |
gen-1 | Display (load) | load | Text (e.g. "75%", "IDLE") |
gen-1 | Display (fuel level) | fuelLevel | Text (e.g. "85%", "LOW") |
gen-1 | Display (label) | value | Text (e.g. "GEN-1") |
gen-1-fuel-inlet | Port — fuel connection | connected | true / false |
Additional hotspots (disabled by default, can be enabled for custom models): exhaust temp display, runtime hours display, power outlet port, auditory alarm, emergency stop button.
Fuel Tank
Location: Generator Yard — 2 units (fuel-tank-1, fuel-tank-2)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
fuel-tank-1 | Display (fuel level) | fuelLevel | Text (e.g. "90%", "EMPTY") |
fuel-tank-1 | LED indicator (fuel level) | fuelLevelStatus | "ok" (green), "warning" (amber), "failed" (red) |
fuel-tank-1 | Display (label) | value | Text (e.g. "TANK-1") |
fuel-tank-1-fuel-outlet | Port — fuel connection | connected | true / false |
Additional hotspots (disabled by default): fill cap, shutoff valve, low fuel alarm.
Fuel Pipe
Location: Generator Yard — 2 units connecting tanks to generators (fuel-pipe-1, fuel-pipe-2)
Each fuel pipe runs from a fuel tank to its paired diesel generator. The pipe has an interactive shutoff valve at the midpoint.
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
fuel-pipe-1 | Rotary dial — shutoff valve | open | true (open, fuel flowing) / false (closed) |
fuel-pipe-1 | LED indicator (valve status) | valveOpen | true (green) / false (red) |
fuel-pipe-1 | Display (label) | value | Text (e.g. "PIPE-1 (TANK-1 → GEN-1)") |
Additional hotspots (disabled by default): flow rate display, leak alarm.
Pipe pairings:
fuel-pipe-1connectsfuel-tank-1→gen-1fuel-pipe-2connectsfuel-tank-2→gen-2
Fire Extinguisher
Location: Generator Yard — 1 unit near the yard entrance (yard-extinguisher)
| Object ID | Interaction | Property | Possible Values |
|---|---|---|---|
yard-extinguisher | Lever latch — squeeze handle | discharged | true (used) / false (ready) |
yard-extinguisher | LED indicator (pressure) | pressure | "ok" (green), "low" (red) |
yard-extinguisher | Display (label) | value | Text (e.g. "EXT-1") |
yard-extinguisher-pin | Spring pin — safety pin | pulled | true (pin removed) / false (pin in place) |
Additional hotspot (disabled by default): wall bracket.
Custom Equipment Types
The AI layout and scenario builders can create custom equipment types with procedural geometry and hotspots. These are stored in the layout’s customEquipmentTypes field and rendered by the ProceduralEquipment component.
Common custom types include:
- Thermal Scanner — handheld device with power button, trigger, LED, and display
- DCIM Workstation — desk with monitor, keyboard area, and interactive buttons (acknowledge alarm, clear alarm)
- Blanking Panel Rack — wall-mounted storage with removable blanking panels
Custom equipment hotspots work the same as built-in equipment — they can be targeted by task-step validation, pre-conditions, and state reactions using the equipment placement ID and hotspot key.
To add custom equipment: Use the AI layout editor and describe the equipment you need. The AI will create the type definition (geometry + hotspots) and place it in the layout. You can then fine-tune appearance and hotspot positions with follow-up prompts.
Configuring Scenarios
Pre-Conditions
Pre-conditions set initial equipment state before the trainee starts. Each pre-condition has three fields:
| Field | Description | Example |
|---|---|---|
objectId | The equipment object ID | rack-A3-drive2 |
property | The state property to set | status |
value | The initial value | "failed" |
Common pre-condition examples:
Failed drive: { objectId: "rack-A3-drive2", property: "status", value: "failed" }
Rack degraded label: { objectId: "rack-A3", property: "value", value: "A3 — DEGRADED" }
CRAH overheating: { objectId: "crah-1", property: "temp", value: "28" }
Dirty filter warning: { objectId: "crah-1", property: "filterDirty", value: true }
Fire alarm active: { objectId: "fire-panel", property: "status", value: "warning" }
Fire panel armed: { objectId: "fire-panel", property: "armed", value: true }
UPS low battery: { objectId: "ups-1", property: "batteryLevel", value: "15%" }
PDU overloaded: { objectId: "pdu-1", property: "load", value: "OVERLOAD" }
PDU breaker tripped: { objectId: "pdu-1-switch3", property: "on", value: false }
Network port down: { objectId: "patch-1-port5", property: "connected", value: false }
Generator running: { objectId: "gen-1", property: "on", value: true }
Generator fuel low: { objectId: "gen-1", property: "fuelLevel", value: "LOW" }
Fuel tank level: { objectId: "fuel-tank-1", property: "fuelLevel", value: "90%" }
Fuel valve closed: { objectId: "fuel-pipe-1", property: "open", value: false }
Extinguisher used: { objectId: "yard-extinguisher", property: "discharged", value: true }
Powered displays: set the power switch too
Many canvas gauges in the equipment catalogue — voltmeters, ammeters, load meters, fuel gauges, RPM dials, battery indicators — are power-gated. Each such gauge declares a powerProperty naming the hotspot key of the switch, breaker, or ignition that energises it. The gauge only displays a meaningful reading when that named hotspot is set to a truthy value. When the power source is off (or unset), the gauge clamps to its minimum value and your pre-conditioned reading is silently ignored.
This models real-world behaviour: a voltmeter reads zero when its breaker is open; a tachometer reads zero when the engine is stopped.
Practical rule: whenever you set a pre-condition for a gauge value, also set a pre-condition for its powerProperty to true in the same scenario — unless you specifically want the gauge to start dark (e.g. the trainee’s first task is to energise the equipment).
Main switchboard, voltage reading visible:
{ objectId: "main_switchboard-1", property: "main-breaker", value: true }
{ objectId: "main_switchboard-1", property: "bus-voltage-display", value: 415 }
Diesel generator under load, gauge reading visible:
{ objectId: "gen-1", property: "power-switch", value: true }
{ objectId: "gen-1", property: "load-display", value: 1200 }
UPS with battery indicator visible:
{ objectId: "ups-1", property: "power-button", value: true }
{ objectId: "ups-1", property: "battery-display", value: 85 }
Two ways to discover whether a gauge is power-gated:
- Hover the property in the pre-conditions editor dropdown — the helper text shows
gated by <powerProperty>when applicable. - AI scenarios — the AI’s
get_equipment_hotspotstool surfaces the dependency in its output (the line for the gauge ends withgated by powerProperty=...).
Exception: tube-style gauges (sight glasses — fuel levels, water levels) are passive and ignore the power gate. They always show the live value.
The pre-conditions tool returns a warning when you set a gauge value without also setting its power switch, but accepts the call anyway (in case the dark-gauge state is intentional). If you saved a scenario before this guidance landed and the gauges aren’t showing the readings you set, the missing power-switch pre-conditions are the most likely cause.
Toolbox (Hand-carry items)
The Toolbox section lets you declare items the trainee starts the scenario with on a follower hip-belt strip — tools, PPE, and LOTO accessories. Items the trainee picks up off the belt with X appear in their inventory; Y drops them back. The strip auto-hides when no items are declared.
Each toolbox row has two fields:
| Field | Description | Example |
|---|---|---|
| Equipment type | The reference type (dropdown of toolbox-eligible items) | hard_hat, multimeter, loto_padlock |
| Count | How many of this type to start with | 1 |
What’s eligible: the dropdown is filtered to the three classes of items that physically belong on a person rather than in a layout:
- Tools — hand tools (multimeter, screwdriver, torque wrench, gas detector, …). Identified by
equipmentType: 'tools'in the reference data. - PPE — personal protective equipment (hard hat, safety glasses, hi-vis vest, ear muffs, gloves, face mask, steel-capped boots, welding helmet). Identified by a
'ppe'tag. - LOTO accessories — items that physically attach to host equipment (padlocks, hasps, tags, permits). Identified by
mountSurface: 'equipment'in the reference data.
These items are hidden from the layout equipment picker — they belong on the belt, not in a room.
Replenishment: the toolbox refills to its declared capacity every time the scenario (re-)starts, so a trainee who lost or misplaced an item on a prior attempt gets a fresh set on retry.
Task Steps — Validation Types
Each task step has a validationType that determines how the system checks whether the trainee has completed it.
object_interaction
The trainee must interact with a specific object (toggle, grab, release).
| Config Field | Description | Example |
|---|---|---|
targetId | Object to interact with | "rack-A3-door" |
action | Expected action type | "toggle", "grab", "release" |
currentState | State the object is in when the scenario starts | "closed", "off" |
requiredState | State the object should be in after this step (for auto-grading) | "open", "removed" |
button_press
The trainee must press a specific button or switch.
| Config Field | Description | Example |
|---|---|---|
targetId | Button to press | "epo-button", "fire-panel", "pdu-1-switch3" |
currentState | State the button is in when the scenario starts | "off" |
requiredState | State the button should be in after this step | "pressed", "on" |
location_visit
The trainee must navigate to a specific room.
| Config Field | Description | Example |
|---|---|---|
zoneId | Room zone identifier | "zone-data-hall", "zone-vestibule", "zone-cooling", "zone-power", "zone-network", "zone-generator-yard" |
cable_action
The trainee must plug or unplug a cable.
| Config Field | Description | Example |
|---|---|---|
targetId | Cable/port to act on | "patch-1-port5", "gen-1-fuel-inlet", "fuel-tank-1-fuel-outlet" |
action | Plug or unplug | "plug", "unplug" |
currentState | State the cable is in when the scenario starts | "disconnected" |
requiredState | State the cable should be in after this step | "connected" |
observation
The trainee must look at something for a minimum duration.
| Config Field | Description | Example |
|---|---|---|
targetId | Object to observe | "crah-1", "rack-A3-drive2", "gen-1", "fuel-tank-1" |
minDurationSeconds | How long to look | 3, 5 |
equipment_move
The trainee must pick up a piece of equipment and drop it near a target location.
| Config Field | Description | Example |
|---|---|---|
dropTargetId | Equipment to drop near | "rack-B4" |
targetPosition | Auto-derived from dropTargetId | { x: 3, y: 0, z: -0.5 } |
snapRadius | Distance threshold for valid drop (metres) | 1.5 |
The trainee grabs equipment (X on the left VR controller, X key on desktop), carries it to the target, and drops it (Y on the left VR controller, Y key on desktop). The step completes when the equipment is dropped within the snap radius.
equipment_grab
The trainee must pick up an item — either a specific placement in the layout, or any item of a given type from the toolbox strip. Step completes as soon as the correct item is grabbed.
The editor surfaces a toggle next to the Target field with two modes:
| Mode | What it grades | Config field used | When to use |
|---|---|---|---|
| Specific item in layout | A specific placed equipment | targetId (placement id) | “Pick up the thermal scanner sitting on the rack” |
| From toolbox | Any take of this type off the belt | equipmentType (reference type) | “Don the hard hat”, “Take a padlock” |
The “From toolbox” dropdown is scoped to types you declared in the scenario’s Toolbox section — if the toolbox is empty, the option is disabled. Use this for any step where the trainee must put on PPE, take a tool from their kit, or grab a LOTO accessory off their belt.
Use Specific item in layout when the action is “take the tool from where it sits” and the drop location is handled by the next step (or by tool_use validation).
tool_use
The trainee must be holding a tool of a given category and cause a specific hotspot on another piece of equipment to reach the expected state. Polled continuously (no event required) — works for “scan the thing” / “spray the thing” / “measure the thing” flows.
| Config Field | Description | Example |
|---|---|---|
toolCategory | Category of the held tool | "fire_suppression", "thermal_imaging", "fastener" |
targetId | Equipment being acted on | "gen-1" |
hotspotKey | Hotspot on the target | "temp-reading" |
expectedState | Value that counts as success | "ok", "true" |
The trainee grabs the tool first (via an equipment_grab step or just by picking it up from the layout), then points/triggers it at the target. Equipment opts into this by declaring a toolCategory on its placement.
audio_cue
Plays a sound when the step activates. The sound is environmental stimulus — there’s no expected reaction from the trainee. The step ends on a timer or when the sound finishes naturally.
| Config Field | Description | Example |
|---|---|---|
audio.soundKey | Library sound key (built-in or org:.../...) | "fire-alarm-t3", "evac-siren" |
audio.cueCompletion.kind | How the step ends | "auto-advance-after-seconds" or "auto-advance-on-sound-end" |
audio.cueCompletion.seconds | (for auto-advance-after-seconds) | 5 |
audio.continueSound | If true, sound keeps playing into subsequent steps | false (default) |
Use audio_cue when the recognition of a sound is the training value (the alarm fires, the scenario moves on, the trainee experiences the environment). Use audio_response instead when you want to assess what the trainee does about it. auto-advance-on-sound-end is only valid for one-shot sounds — loops have no natural end.
audio_response
Plays a sound and validates the trainee’s reaction. The step waits for the configured response: either a hotspot interaction (acknowledge button, silencer switch) or a zone entry (muster point, safe area).
| Config Field | Description | Example |
|---|---|---|
audio.soundKey | Library sound key | "fire-alarm-t3" |
audio.response.kind | Response shape | "hotspot" or "zone" |
audio.response.targetId | (hotspot) Equipment being interacted with | "fire-panel-1" |
audio.response.hotspotKey | (hotspot) Hotspot on the target | "acknowledge" |
audio.response.expectedState | (hotspot) Value that counts as success | "true" |
audio.response.zoneId | (zone) Zone the trainee must reach | "zone-muster" |
audio.timeoutSeconds | Optional. Step fails if no response in this time | 30 |
audio.continueSound | If true, sound keeps playing past completion | false (default) |
audio.visualMessage | Accessibility: HUD message shown while step is active | "Fire alarm — acknowledge at the panel" |
audio.visualSeverity | HUD colour: "normal", "warning", or "danger" | "danger" |
The visual cue HUD supports deaf trainees, muted hardware, and noisy training environments. Setting it is strongly recommended for any safety-critical audio_response step. It only appears on audio_response (not audio_cue) — see the Temporal Audio section for the rationale.
build_rules
Reserved for Produce-mode scenarios — validation is driven by the step’s buildRules list (evaluated server-side on Submit and live in the editor panel). Authors don’t set this directly; it’s applied automatically when a Produce-mode step is saved. See Produce Mode Scenarios and the Build-Rules Cookbook.
Current State vs Required State
Each task step can optionally specify two state fields:
-
Current State — The state the object is in when the scenario begins. This supplements the scenario’s pre-conditions and ensures the VR environment displays the correct initial state for the equipment. For example, if a step requires the trainee to open a rack door, set the current state to
"closed"so the door appears closed when the scenario loads. -
Required State — The state the object should be in after the trainee completes this step. This serves as an auto-grading rubric: the system checks whether the trainee’s action resulted in the correct final state. For example, if the step is “Open rack A3 door”, the required state would be
"open".
Zone IDs
| Zone ID | Room |
|---|---|
zone-data-hall | Main Data Hall |
zone-vestibule | Entry Vestibule |
zone-cooling | Cooling / Mechanical Room |
zone-power | Power Room |
zone-network | Control Room |
zone-generator-yard | Generator Yard (outdoor) |
Step Videos
Each task step can optionally have a video assigned from the organisation’s Video Library. When the trainee reaches a step with a video, a centre-screen overlay plays the video automatically.
How it works:
- Videos are registered in the Video Library page (admin/trainer) by entering a Vimeo video ID or URL.
- In the scenario editor, each step has a Step Video dropdown to select from the library.
- During VR playback, the video overlay appears in front of all other HUD elements.
- Controls: play/pause, restart, and close buttons appear semi-transparently over the video (fade in on hover, fade out during playback).
- The video auto-dismisses 2 seconds after playback ends, or the trainee can close it manually at any time.
- Video playback is supplementary — the step’s validation still works via its normal mechanism (the trainee does not need to finish watching the video to proceed).
When to use step videos:
- Demonstrating a physical procedure (e.g. how to operate a valve, how to don PPE) before the trainee attempts it.
- Providing visual safety briefings at the start of a scenario.
- Supporting trainees with low literacy or numeracy who may struggle with text-based HUD instructions.
- Showing equipment-specific training clips alongside the relevant hands-on step.
Example: A scenario for offshore emergency response might have:
- Step 1: Location visit to muster station — video: “Emergency muster procedure” (60s safety briefing)
- Step 2: Interact with life jacket station — video: “How to don a life jacket” (30s demonstration)
- Step 3: Interact with lifeboat entry hatch — no video (text instructions sufficient)
One Validation Surface Per Step
Each task step has a single validation contract — its validationType and the validationConfig that goes with it (see Task Steps — Validation Types above). The step completes when that one contract is satisfied.
If a procedure needs the trainee to perform several actions in sequence, model it as several steps rather than packing actions into one. This keeps each step’s pass/fail signal unambiguous, makes branching predictable, and shows the trainee a clear next action in the task panel.
Example — “lock out PDU A”:
Step 1 location_visit zone-power
Step 2 object_interaction pdu-1-main → off
Step 3 equipment_grab loto_padlock (from toolbox)
Step 4 tool_use padlock applied to pdu-1-main
Step 5 observation pdu-1 power-led for 3 s (verify de-energised)
Each step grades one action. The trainee sees one task at a time on the HUD; branching can react to any individual step’s outcome.
Conditional Branching (Advanced)
By default, scenario steps execute in a fixed linear sequence. Conditional branching allows you to change which step the trainee goes to next based on what they did (or didn’t do) on the current step.
Each step can have optional branch rules — evaluated in order after the step completes, fails, or is skipped. The first matching rule determines the next step. If no rule matches, the scenario advances linearly as usual.
Branch Condition Types
| Condition | Description | Use Case |
|---|---|---|
| Step completed | The trainee completed the step successfully | Route to the next section after passing |
| Step failed | The trainee answered incorrectly or failed validation | Route to a remedial sequence |
| Step skipped | The trainee skipped an optional step | Continue on the main path |
| Equipment in state | A specific equipment hotspot is in a given state | Route based on what the trainee has done to equipment — also covers “the trainee chose X” patterns by reading the state the choice left behind |
| Time exceeded | The trainee took longer than N seconds on the step | Timeout consequences — branch to a failure path |
| Always (unconditional) | Always matches — acts as a catch-all or “go to” | Jumping back to retry, or converging branches |
Branch Targets
Each rule specifies a target:
- Step N — jump to a specific step in the scenario (by step number)
- End Scenario — immediately complete the scenario
Setting Up Branch Rules
- Edit a scenario and expand a task step.
- Click + Advanced: Branch Rules at the bottom of the step card.
- Click Add Branch Rule.
- Select a condition type, configure condition-specific fields, and select the target step.
- Add multiple rules if needed — they evaluate top to bottom, first match wins.
- Optionally set a Branch Group label (e.g. “Main Path”, “Remedial”) to organise steps visually.
Steps with branch rules show a purple badge (e.g. “2 branches”) in the step header.
Practical Patterns
Wrong-action remediation:
Step 3: "Open the correct breaker" (object_interaction on pdu-1-switch3 → off)
→ If step failed → Step 7 (remedial walkthrough)
→ If step completed → Step 4 (continue main path)
Step 9: "Now try again" (end of remedial sequence)
→ Always → Step 3 (retry the action)
Triage / decision tree (state-driven):
Step 1: "Identify the primary hazard and press the matching panel button"
(object_interaction on hazard-panel)
→ If equipment hazard-panel.selected = "electrical" → Step 10 (electrical response)
→ If equipment hazard-panel.selected = "chemical" → Step 20 (chemical response)
→ If equipment hazard-panel.selected = "fire" → Step 30 (fire response)
Competency skip:
Step 5: "Identify the correct breaker by toggling it off"
→ If step completed → Step 12 (skip to next section)
→ If step failed → Step 6 (detailed walkthrough)
Time-pressure consequence:
Step 8: "Isolate the leak before pressure reaches critical"
→ If time exceeded (60 seconds) → Step 15 (consequence path)
→ If step completed → Step 9 (continue normal path)
Cycle Detection
Branch rules can jump backwards (e.g. “try again” loops). To prevent infinite loops, the engine limits how many times a step can be revisited. The default is 3 retries — configurable via maxStepRetries in scenario settings. After exceeding the limit, the engine skips ahead.
Path History
When branching is used, the trainee’s actual path through the scenario is recorded in the attempt results as pathHistory. This shows each step visited, the outcome, which branch condition matched, and timestamps — useful for reviewing how trainees navigated decision points.
Difficulty Levels
beginner— Guided tasks, hints enabled, generous time limitsintermediate— Some complexity, multiple rooms involvedadvanced— Time pressure, consequences for mistakes, multi-system procedures
State Reactions
State reactions define cause-and-effect chains between equipment. When one hotspot changes state, another hotspot is automatically updated. This makes the facility feel realistic — pressing a button updates a display, toggling a switch lights an LED, etc.
| Reaction Field | Description | Example |
|---|---|---|
whenObjectId | Equipment whose state triggers the reaction | "dcim-workstation" |
whenProperty | Hotspot key to watch | "acknowledge-alarm" |
whenValue | Value that triggers the reaction | "true" |
thenObjectId | Equipment to update | "dcim-workstation" |
thenProperty | Hotspot key to set | "main-screen" |
thenValue | Value to set | "ALARM ACKNOWLEDGED" |
Common reaction examples:
Button press updates display:
WHEN dcim-workstation.acknowledge-alarm = "true"
THEN SET dcim-workstation.main-screen = "ALARM ACKNOWLEDGED"
Button press clears alarm:
WHEN dcim-workstation.clear-alarm = "true"
THEN SET dcim-workstation.main-screen = ""
Power button lights LED:
WHEN thermal-scanner.power-button = "true"
THEN SET thermal-scanner.power-led = "true"
Tips for state reactions:
- Reactions fire immediately when the trigger condition is met
- Multiple reactions can chain together (button → display → LED)
- Use reactions to simulate realistic equipment behaviour without code changes
- For buttons that control LEDs, consider using the same hotspot key instead of a reaction (simpler)
Pseudo-objects
State reactions can also target three pseudo-objects that aren’t equipment placements. They behave the same as equipment in the reaction syntax — you just use a reserved id instead of a real placement id.
| Pseudo-object | When/Then? | What it does |
|---|---|---|
narrator | THEN only | Shows a cinematic text overlay. Set thenObjectId="narrator", thenProperty="__narrative". The Then-value field expands into a structured editor: enter the narrative text and pick a Stop mode — Auto (8 s + fade), Timed (custom seconds), Dismissable (trainee clicks to close), Until next step, or Persistent (clears when another reaction overwrites it). |
audio | THEN only | Plays or stops a temporal sound. Set thenObjectId="audio", thenProperty=<sound-key>, thenValue="play" or "stop". See Temporal Audio. |
player | WHEN only | Fires on space transitions. Set whenObjectId="player", whenProperty="currentZone", whenValue=<zoneId> or "__none" (player left all zones). |
Pseudo-object examples:
Press a button → play a fire alarm:
WHEN fire-test-panel.test-button = "true"
THEN SET audio.fire-alarm-t3 = "play"
Press acknowledge → silence the alarm:
WHEN fire-test-panel.acknowledge-button = "true"
THEN SET audio.fire-alarm-t3 = "stop"
Enter the muster point → stop the evac siren and show a narrative:
WHEN player.currentZone = "zone-muster"
THEN SET audio.evac-siren = "stop"
WHEN player.currentZone = "zone-muster"
THEN SET narrator.__narrative = "You have reached the muster point. Well done."
Tickets
Scenarios can include a support ticket — a work order that describes the problem the trainee needs to investigate. Tickets are available in both single-player and cooperative modes.
| Ticket Field | Description | Example |
|---|---|---|
subject | Short title for the work order | "Investigate Overheating at Rack B4" |
description | Detailed background information | "Temperature alarm triggered at 14:30..." |
category | Type of work | General, Incident, Maintenance, Inspection, Safety, Change Request |
priority | Urgency level | Low, Medium, High, Critical |
dueDate | Optional deadline | "2026-03-25" |
How tickets work:
- The ticket is defined in the scenario editor when “Tickets enabled” is checked
- When a trainee starts an attempt, a fresh ticket instance is created
- The ticket appears in the trainee’s HUD (VR and desktop)
- Trainees can add notes to the ticket during the exercise (e.g. observations, actions taken)
- Notes are timestamped and attributed to the player
- In cooperative mode, both players see the ticket and each other’s notes in real time
- Trainers can review the full ticket and notes history in the assignment/result detail page
Spawn Rooms
You can specify which room each player starts in:
| Setting | Description | Default |
|---|---|---|
spawnRoomId | Room where Player 1 spawns | Layout’s default entry point |
coopSpawnRoomId | Room where Player 2 spawns (cooperative only) | Same as Player 1 |
Use the room select dropdown in the scenario editor to choose from available spaces in the layout.
Cooperative Scenarios
Cooperative (2-player) scenarios have two roles:
- Field Technician — physically navigates the facility, interacts with equipment, follows procedure steps
- Control Room Operator — monitors equipment from the control room, coordinates with the field technician
Configuring cooperative scenarios:
- Enable Cooperative mode in scenario settings
- Set Player 1 spawn room (typically the Data Hall for the field technician)
- Set Player 2 spawn room (typically the Control Room for the operator)
- Enable Tickets and define a ticket describing the work order
- Design task steps that require both players to coordinate (e.g. field technician inspects equipment, operator acknowledges alarms)
- Both players communicate via built-in voice chat — no external tools needed
Role assignment: The assigned trainee (the user the scenario was assigned to) always becomes the field technician. The other player who joins the session becomes the control room operator. This is automatic — roles are not chosen by the players.
Important: Each player must use a separate VR headset paired to their own account. The lobby shows “Signed in as: [email]” — verify identity before joining.
How-to Guide
On the scenario edit page, you can write a preparation guide for trainees using the TipTap WYSIWYG editor. This guide appears on the trainee’s assignment detail page before they launch the exercise. Use it to explain the procedure, safety considerations, and what to expect.
Click Generate with AI to auto-generate a how-to guide from the scenario’s steps and description. You can then edit the generated content as needed.
Learning Resources
Upload PDFs and images on the scenario edit page to provide reference materials for trainees. These resources appear on the trainee’s assignment detail page, where they can click to open them in a new tab.
Common uses:
- Equipment reference manuals
- Safety data sheets
- Facility diagrams and floor plans
- Photographs of real equipment
AI Scenario Builder
The fastest way to create a scenario is with the AI Scenario Builder:
- Navigate to Scenarios in the sidebar.
- Click AI Builder.
- Select the facility layout the scenario will use.
- Describe the training procedure in natural language.
- The AI reads the layout’s equipment and rooms, then generates a sequence of task steps (each with its own validation contract), pre-conditions, state reactions, custom equipment, and a how-to guide.
- Review the scenario preview on the right panel. Send follow-up messages to refine.
- A green Ready indicator appears when the AI is done. Click Save Scenario.
View past AI conversations under AI History in the sidebar. Browse by layout or scenario and click to view in read-only mode.
Narrative Popups
Scenarios can include narrative text that appears as a cinematic overlay during the exercise to provide story context or instructions to the trainee. Wire them up as state reactions with thenObjectId="narrator" and thenProperty="__narrative" (see the Pseudo-objects table); the Then-value editor exposes the narrative text plus a Stop mode:
| Stop mode | Behaviour |
|---|---|
| Auto | Displays for 8 seconds, then fades out (the default). |
| Timed | Displays for a custom number of seconds, then fades out. |
| Dismissable | Stays until the trainee clicks the close control on the overlay. |
| Until next step | Stays until the scenario advances to the next task step, then clears immediately. |
| Persistent | Stays indefinitely. Clears only when another reaction writes a new narrator value (an empty string is the explicit-clear signal). |
Pick the mode that matches the role of the popup: short scene-setting → Auto; “read this before continuing” → Dismissable or Until next step; ambient context across many steps → Persistent (with an explicit clear at the end).
Temporal Audio
Scenarios can play event-driven sounds — fire alarms, evacuation sirens, industrial horns, telephone rings, doorbells, timer beeps. These are distinct from the ambient audio that loops while a trainee is in a particular space; temporal sounds fire in response to events, play for a defined period, and stop.
There are three ways to wire temporal audio into a scenario:
audio_cuestep type — environmental stimulus. The sound plays, the scenario moves on. Use when recognition is the training value (the alarm fires, the trainee notices, the exercise continues).audio_responsestep type — stimulus + assessment. The sound plays, the scenario waits for the trainee to do the right thing (acknowledge a panel, walk to a muster point). Use when response is the training value.- State reactions via the
audiopseudo-object — fire/stop sounds in response to any other event. Useful for “sound the alarm when the temperature gets too high” patterns or for stopping a sound that was started by apre-conditionor another reaction.
Audio library: scenarios can use platform-shipped sounds (fire alarm T3, evacuation siren, industrial horn, telephone ring, doorbell, timer expiry) or sounds the organisation has uploaded into its own audio library (Sidebar → Audio Library, admin only). Uploaded sounds let organisations train against the exact sounds trainees will encounter in the field — important for safety-critical recognition training where a generic substitute would be unsafe.
Looping vs one-shot: loops play until explicitly stopped (alarms, sirens). One-shots play once (doorbell, phone ring, timer beep). This is a property of the sound, not the step — the runtime handles it automatically.
Accessibility (visual cues): audio_response steps support a visual cue HUD — a top-centre flashing message shown while the step is active. Strongly recommended for safety-critical scenarios. Set the audio.visualMessage and audio.visualSeverity fields on the step. The HUD respects the trainee’s prefers-reduced-motion OS setting (flash becomes a static border) and hides alongside the other HUDs when the trainee right-grips the controller.
Visual cues only fire on audio_response, not audio_cue. audio_cue is environmental stimulus by design — a HUD message there would contradict the “this is ambient context” framing. If a sound carries instructional weight, model it as audio_response (even a trivial zone response works) so the visual cue surfaces correctly.
Authoring tips:
- Use audio sparingly. Silent training is fine for most scenarios. Audio earns its place in emergency-response, evacuation, control-room-attention, and timer-driven training.
- Sound the alarm at scenario start via a pre-condition (
audio.<key>=play) when the scenario opens in medias res. - Always model the stop path explicitly. The trainee should be able to silence an alarm by completing the right action; a scenario that leaves the alarm playing forever is fatiguing.
- Pair an
audio_responsestep with a clearvisualMessagefor any sound the trainee must understand to pass. - Use
audio.continueSound = truewhen an alarm should keep ringing across multiple response steps (e.g. fire alarm during evacuation + muster + headcount). Add an explicit stop reaction at the end of the sequence.
VR Controls Reference
When authoring scenarios, keep the following controls in mind as they affect how trainees interact with equipment:
Grab and Drop:
- VR headset: X button (left controller) to grab equipment you are pointing at, Y button (left controller) to drop the currently-selected inventory item at the cursor.
- Desktop: X key to grab, Y key to drop.
- Equipment follows pointer/beam. Drop near a snap target to snap into place.
View height (VR only): A button (right controller) raises the point of view, B button (right controller) lowers it. Useful for stepping over rungs, looking over high equipment, or simulating ladders.
Inventory system: Trainees can carry multiple items. Grabbed items are added to an inventory bar at the bottom of the view (desktop) or a wrist-anchored inventory panel (VR — roadmap). On desktop, click a slot to select it before dropping; in VR today the active slot is selected automatically — multi-item inventory management in VR is on the roadmap.
Hotspot discovery mode: A toggle button on the Controls HUD highlights all interactive hotspots in the scene with a glow effect. Trainees use this to find equipment they need to interact with.
VR HUD toggle: Right grip button or “Hide HUD” button on Controls panel to show/hide the scenario tablet and ticket panel.
Tips for Scenario Authors
- Always set pre-conditions to establish the problem state before the trainee begins
- Start with a location_visit step so the trainee navigates to the correct room
- Use observation steps for inspection tasks — they require the trainee to look at the right thing
- Use equipment_move steps for tasks where trainees carry tools (thermal scanner, fire extinguisher). Set the target equipment and snap radius
- Mark non-critical steps as optional (e.g. closing a door after the procedure)
- Write clear hint text for each step — hints are shown in practice mode when enabled
- Use state reactions to make equipment respond realistically (button → display update, switch → LED)
- Create tickets for scenarios that simulate real-world work orders — trainees practice documenting observations
- Test your scenarios by assigning them to yourself (admins/trainers can self-assign)
- Use the AI Scenario Builder for faster creation — describe the procedure in natural language and the AI generates steps, pre-conditions, state reactions, and a how-to guide automatically
- Write a how-to guide or generate one with AI — trainees read this before launching the exercise
- Attach learning resources (PDFs, images) for reference materials trainees can review beforehand
- Generator yard scenarios — include a
location_visittozone-generator-yardand observation steps for fuel level checks - Cooperative scenarios — set different spawn rooms for each player and design steps that require coordination