Reference Verse compiles

lock_device: Pirate Vault Doors That Open on Cue

Deep in a sun-drenched cove, a pirate vault door stands between your players and glory. The `lock_device` is the Verse API that controls whether a door is locked or unlocked, and whether it is open or closed — two independent states you can drive entirely from code. Pair it with a `trigger_device` pressure plate and a `hud_message_device` and you have a complete puzzle loop without a single channel wire.

Updated Examples verified on the live UEFN compiler
Watch the Knotlock_device in ~90 seconds.

Overview

The lock_device wraps any UEFN door asset and exposes six methods that cover every state transition a door can have:

  • Lock / Unlock / ToggleLocked — control whether the door can be opened by a player.
  • Open / Close / ToggleOpened — physically swing the door regardless of lock state (useful for scripted cinematics or auto-doors).

Reach for lock_device whenever you need scripted door control: a vault that opens only after a puzzle is solved, a jail cell that slams shut when a player enters, a treasure room that unlocks after all enemies are defeated, or an auto-sliding door triggered by proximity.

Important: lock_device only works with props/assets that have a door component attached. A plain static mesh will not respond.

API Reference

lock_device

Used to customize the state and accessibility of doors. lock_device only works with assets that have a door attached.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).

lock_device<public> := class<concrete><final>(creative_device_base):

Methods (call these to make the device act):

Method Signature Description
Lock Lock<public>(Agent:agent):void Locks the door. Agent is the instigator of the action.
Unlock Unlock<public>(Agent:agent):void Unlocks the door. Agent is the instigator of the action.
ToggleLocked ToggleLocked<public>(Agent:agent):void Toggles between Lock and Unlock. Agent is the instigator of the action.
Open Open<public>(Agent:agent):void Opens the door. Agent is the instigator of the action.
Close Close<public>(Agent:agent):void Closes the door. Agent is the instigator of the action.
ToggleOpened ToggleOpened<public>(Agent:agent):void Toggles between Open and Close. Agent is the instigator of the action.

trigger_device

Used to relay events to other linked devices.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from trigger_base_device.

trigger_device<public> := class<concrete><final>(trigger_base_device):

Events (subscribe a handler to react):

Event Signature Description
TriggeredEvent TriggeredEvent<public>:listenable(?agent) Signaled when an agent triggers this device. Sends the agent that used this device. Returns false if no agent triggered the action (ex: it was triggered through code).

Methods (call these to make the device act):

Method Signature Description
Trigger Trigger<public>(Agent:agent):void Triggers this device with Agent being passed as the agent that triggered the action. Use an agent reference when this device is setup to require one (for instance, you want to trigger the device only with a particular agent.
Trigger Trigger<public>():void Triggers this device, causing it to activate its TriggeredEvent event.
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
SetMaxTriggerCount SetMaxTriggerCount<public>(MaxCount:int):void Sets the maximum amount of times this device can trigger. * 0 can be used to indicate no limit on trigger count. * MaxCount is clamped between [0,20].
GetMaxTriggerCount GetMaxTriggerCount<public>()<transacts>:int Gets the maximum amount of times this device can trigger. * 0 indicates no limit on trigger count.
GetTriggerCountRemaining GetTriggerCountRemaining<public>()<transacts>:int Returns the number of times that this device can still be triggered before hitting GetMaxTriggerCount. Returns 0 if GetMaxTriggerCount is unlimited.
SetResetDelay SetResetDelay<public>(Time:float):void Sets the time (in seconds) after triggering, before the device can be triggered again (if MaxTrigger count allows).
GetResetDelay GetResetDelay<public>()<transacts>:float Gets the time (in seconds) before the device can be triggered again (if MaxTrigger count allows).
SetTransmitDelay SetTransmitDelay<public>(Time:float):void Sets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered.
GetTransmitDelay GetTransmitDelay<public>()<transacts>:float Gets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered.

hud_message_device

Used to show custom HUD messages to one or more agents.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).

hud_message_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
ShowMessageEvent ShowMessageEvent<public>:listenable(agent) Called when a Message has been Shown on-screen. Returns an Agent if it was Shown on a specified Agent's screen.
HideMessageEvent HideMessageEvent<public>:listenable(agent) Called when a Message has been Hidden on-screen. Returns an Agent if it was Hidden from a specified Agent's screen.
ClearAllMessagesEvent ClearAllMessagesEvent<public>:listenable(agent) Called when all queued Messages from all players that are affected by this HUD Message Device have been cleared.

Methods (call these to make the device act):

Method Signature Description
Show Show<public>(Agent:agent):void Shows the currently set HUD Message on Agents screen. Will replace any previously active message. Use this when the device is setup to target specific agents.
Show Show<public>():void Shows the currently set Message HUD message on screen. Will replace any previously active message.
Hide Hide<public>():void Hides the HUD message.
Hide Hide<public>(Agent:agent):void Hides the currently set HUD Message on Agents screen. Use this when the device is setup to target specific agents.
Show Show<public>(Agent:agent, Message:message, ?DisplayTime:float Displays a Custom message to a specific Agent that you define.Setting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device.
Show Show<public>(Message:message, ?DisplayTime:float Displays a Custom message that you define for all PlayersSetting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device.
SetDisplayTime SetDisplayTime<public>(Time:float):void Sets the time (in seconds) the HUD message will be displayed. 0.0 will display the HUD message persistently.
GetDisplayTime GetDisplayTime<public>()<transacts>:float Returns the time (in seconds) for which the HUD message will be displayed. 0.0 means the message is displayed persistently.
SetText SetText<public>(Text:message):void Sets the Message to be displayed when the HUD message is activated. Text is clamped to 150 characters.
ClearAllMessages ClearAllMessages<public>():void Clears all queued Messages from all players that are affected by this HUD Message Device.

player

Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse). Inherited members are merged from agent.

player<native><public> := class<unique><persistent><module_scoped_var_weak_map_key><epic_internal>(agent):

Walkthrough

The Scenario

A cel-shaded pirate cove. A heavy vault door blocks the treasure room. Two pressure-plate triggers are hidden on the dock — both must be stepped on (in any order) before the vault unlocks and swings open. A HUD message guides the player through each step.

Level Setup

  1. Place a lock_device on your vault door asset. In its Details panel set Starts Locked = true, Starts Open = false.
  2. Place two trigger_devices (PlateA and PlateB) as pressure plates on the dock. Set Trigger Activation = Player, Max Trigger Count = 1 each.
  3. Place a hud_message_device (HUD). Set Display Time = 3.0 s, Target = Triggering Player.

The Code

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# Localised message helper — Verse requires `message` not raw strings
PirateHint<localizes>(S : string) : message = "{S}"

pirate_vault_device := class(creative_device):

    # ── Editable device references ──────────────────────────────────────
    @editable VaultDoor   : lock_device        = lock_device{}
    @editable PlateA      : trigger_device     = trigger_device{}
    @editable PlateB      : trigger_device     = trigger_device{}
    @editable HUD         : hud_message_device = hud_message_device{}

    # ── Internal state ───────────────────────────────────────────────────
    var PlateATriggered : logic = false
    var PlateBTriggered : logic = false

    # ── Lifecycle ────────────────────────────────────────────────────────
    OnBegin<override>()<suspends> : void =
        # Subscribe to both pressure plates
        PlateA.TriggeredEvent.Subscribe(OnPlateATriggered)
        PlateB.TriggeredEvent.Subscribe(OnPlateBTriggered)

        # Greet the first player to load in (broadcast version — no agent)
        HUD.Show(PirateHint("Find the two hidden dock plates to open the vault!"))

    # ── Plate A handler ──────────────────────────────────────────────────
    OnPlateATriggered(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            set PlateATriggered = true
            HUD.Show(A, PirateHint("Plate A — activated! Find the second plate."))
            CheckVaultCondition(A)

    # ── Plate B handler ──────────────────────────────────────────────────
    OnPlateBTriggered(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            set PlateBTriggered = true
            HUD.Show(A, PirateHint("Plate B — activated! Find the second plate."))
            CheckVaultCondition(A)

    # ── Vault logic ──────────────────────────────────────────────────────
    CheckVaultCondition(Agent : agent) : void =
        if (PlateATriggered? and PlateBTriggered?):
            # Both plates pressed — unlock then open the vault door
            VaultDoor.Unlock(Agent)
            VaultDoor.Open(Agent)
            HUD.Show(Agent, PirateHint("The vault is open — claim your treasure!"))

Line-by-Line Explanation

Lines What's happening
@editable VaultDoor : lock_device Wires the Verse class to the placed lock_device in the level. Without @editable the identifier is unknown at runtime.
@editable PlateA/B : trigger_device The two dock pressure plates.
@editable HUD : hud_message_device The floating pirate hint UI.
PlateA.TriggeredEvent.Subscribe(OnPlateATriggered) Registers our handler; the event fires with ?agent (an optional agent).
HUD.Show(PirateHint(...)) Broadcasts to all players. Uses the Show() no-agent overload.
if (A := MaybeAgent?) Safely unwraps the ?agent; required before passing to any method that expects a concrete agent.
HUD.Show(A, PirateHint(...)) Shows the message only on that player's screen.
VaultDoor.Unlock(Agent) Removes the lock — the door can now be opened.
VaultDoor.Open(Agent) Physically swings the door open, with Agent as the instigator.

Common patterns

Pattern 1 — Toggle a jail cell door when a player re-enters a trigger

A guard shack trigger toggles the cell open/closed each time it fires — great for a repeating patrol mechanic.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

CellHint<localizes>(S : string) : message = "{S}"

jail_toggle_device := class(creative_device):

    @editable CellDoor    : lock_device        = lock_device{}
    @editable GuardTrigger: trigger_device     = trigger_device{}
    @editable HUD         : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        GuardTrigger.TriggeredEvent.Subscribe(OnGuardTriggered)

    OnGuardTriggered(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            # ToggleOpened swings the door open if closed, or closed if open
            CellDoor.ToggleOpened(A)
            HUD.Show(A, CellHint("The cell door shifts..."))

Key call: ToggleOpened(Agent) — one call handles both directions, no extra state variable needed.


Pattern 2 — Lock a door after a player passes through (one-way gate)

A clifftop gate lets a player through, then locks behind them so they cannot backtrack.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

GateHint<localizes>(S : string) : message = "{S}"

one_way_gate_device := class(creative_device):

    @editable CliffGate    : lock_device        = lock_device{}
    @editable PassTrigger  : trigger_device     = trigger_device{}
    @editable HUD          : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        # Allow only one pass — after that the trigger disables itself
        PassTrigger.SetMaxTriggerCount(1)
        PassTrigger.TriggeredEvent.Subscribe(OnPlayerPassed)

    OnPlayerPassed(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            CliffGate.Open(A)
            # Brief pause so the player can walk through
            Sleep(1.5)
            CliffGate.Close(A)
            CliffGate.Lock(A)
            HUD.Show(A, GateHint("The gate locks behind you. No turning back!"))

Key calls: OpenSleepCloseLock — a sequential async chain inside a <suspends> context. SetMaxTriggerCount(1) ensures the trigger fires exactly once.


Pattern 3 — HUD countdown then auto-close a treasure room

After the vault opens, a timed HUD message warns the player, then the door slams shut automatically.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

TimerHint<localizes>(S : string) : message = "{S}"

treasure_timer_device := class(creative_device):

    @editable TreasureDoor  : lock_device        = lock_device{}
    @editable EnterTrigger  : trigger_device     = trigger_device{}
    @editable HUD           : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        EnterTrigger.SetMaxTriggerCount(1)
        EnterTrigger.TriggeredEvent.Subscribe(OnEnterTreasure)

    OnEnterTreasure(MaybeAgent : ?agent) : void =
        if (A := MaybeAgent?):
            TreasureDoor.Unlock(A)
            TreasureDoor.Open(A)
            # Show a persistent warning (DisplayTime 0.0 = persistent)
            HUD.Show(A, TimerHint("You have 10 seconds before the vault seals!"), ?DisplayTime := 0.0)
            Sleep(10.0)
            HUD.Hide(A)
            TreasureDoor.Close(A)
            TreasureDoor.Lock(A)
            HUD.Show(A, TimerHint("The vault has sealed. Escape with your loot!"))

Key calls: HUD.Show(Agent, Message, ?DisplayTime := 0.0) for a persistent message, HUD.Hide(Agent) to clear it, then Close + Lock to seal the room.


Gotchas

1. Lock and Open are independent states

Lock/Unlock controls accessibility; Open/Close controls physical position. A door can be locked AND open at the same time (it stays open but a player cannot close it). Always call Unlock before Open if you want the player to be able to interact with it afterward.

2. ?agent must be unwrapped before use

TriggeredEvent sends ?agent (an optional). Passing it directly to VaultDoor.Unlock(MaybeAgent) is a compile error because the method expects agent, not ?agent. Always unwrap:

if (A := MaybeAgent?):
    VaultDoor.Unlock(A)

3. message is not a plain string

Every hud_message_device method that takes text expects the message type, not a string. Declare a localizer helper at module scope:

MyText<localizes>(S : string) : message = "{S}"

There is no StringToMessage function — the <localizes> specifier is the only way.

4. lock_device needs a door asset

The device silently does nothing if attached to a plain static mesh. In UEFN, choose a prop from the Content Browser that has a door component (look for assets tagged Door in the Creative prop library).

5. Sequential async calls require <suspends>

Chaining OpenSleepClose only works inside a function marked <suspends> (like OnBegin) or a spawned coroutine. Event handler methods are not <suspends> by default — if you need async behaviour inside a handler, spawn a helper:

OnPlateTriggered(MaybeAgent : ?agent) : void =
    if (A := MaybeAgent?):
        spawn { RunDoorSequence(A) }

RunDoorSequence(Agent : agent)<suspends> : void =
    VaultDoor.Open(Agent)
    Sleep(5.0)
    VaultDoor.Close(Agent)
    VaultDoor.Lock(Agent)

6. SetMaxTriggerCount clamps to [0, 20]

Passing a value outside that range is silently clamped. Use 0 for unlimited triggers.

Guides & scripts that use lock_device

Step-by-step tutorials that put this object to work.

Build your own lesson with lock_device

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →