Reference Verse compiles

logic and/or in Verse: Gate Logic for Your Island

Every great Fortnite island moment hinges on a decision: did the player do BOTH things, or at least ONE of them? Verse's `and` and `or` operators let you wire those decisions directly into your devices — no extra logic-gate props needed. In this article you'll build a pirate-dock puzzle where two pressure plates must BOTH be held down before the vault door trigger fires, then extend it so a secret override plate can open the door on its own.

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

Overview

Verse treats and and or as failable-expression combinators, not just boolean operators. Inside an if condition (or any failable context), and requires both sub-expressions to succeed, while or tries each in turn and takes the first success. This maps perfectly onto game logic:

  • AND gate — both crew members must stand on their plates before the treasure vault opens.
  • OR gate — the captain's override plate OR the two-crew plates open the same vault.

Pair these operators with trigger_device (to fire downstream devices and broadcast events) and hud_message_device (to give players real-time feedback) and you have a fully interactive, readable puzzle system with zero extra blueprint nodes.

Reach for and/or whenever you need multi-condition checks that drive device calls — they keep your if guards compact and intention-clear.

API Reference

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.

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):

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.

Walkthrough

The Scene

You're on a 2D cel-shaded pirate dock at golden hour. Two barnacle-crusted pressure plates sit on the dock planks — PlateA (port side) and PlateB (starboard side). When both are triggered within a short window, a trigger_device called VaultTrigger fires to open the treasure vault door. A hud_message_device called StatusHUD keeps the crew informed at every step.

Place These Devices in UEFN

Device @editable name Notes
trigger_device PlateA Pressure plate, port side
trigger_device PlateB Pressure plate, starboard side
trigger_device VaultTrigger Linked to vault door, max 1 trigger
hud_message_device StatusHUD Shown to all players

The Verse Device

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

# Localised message helpers
BothPlatesMsg<localizes>(S : string) : message = "{S}"
PlateAMsg<localizes>(S : string) : message = "{S}"
PlateBMsg<localizes>(S : string) : message = "{S}"
VaultOpenMsg<localizes>(S : string) : message = "{S}"

# dock_vault_logic — AND gate: both plates must fire before the vault opens.
# Place this Verse device on the island and wire the @editable fields.
dock_vault_logic := class(creative_device):

    # --- Editable device references ---
    @editable
    PlateA : trigger_device = trigger_device{}

    @editable
    PlateB : trigger_device = trigger_device{}

    @editable
    VaultTrigger : trigger_device = trigger_device{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

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

    # --- Lifecycle ---
    OnBegin<override>()<suspends> : void =
        # Limit the vault to fire only once
        VaultTrigger.SetMaxTriggerCount(1)

        # Show a persistent hint at game start
        StatusHUD.SetDisplayTime(0.0)   # 0 = persistent
        StatusHUD.Show(BothPlatesMsg("Stand on BOTH dock plates to open the vault!"))

        # Subscribe to both plates
        PlateA.TriggeredEvent.Subscribe(OnPlateATriggered)
        PlateB.TriggeredEvent.Subscribe(OnPlateBTriggered)

    # --- Event handlers ---
    OnPlateATriggered(Agent : ?agent) : void =
        set PlateATriggered = true
        # Show per-agent feedback if we have a real agent, otherwise show global
        if (A := Agent?):
            StatusHUD.Show(A, PlateAMsg("Port plate locked in — waiting for starboard!"))
        else:
            StatusHUD.Show(PlateAMsg("Port plate locked in — waiting for starboard!"))
        CheckBothPlates(Agent)

    OnPlateBTriggered(Agent : ?agent) : void =
        set PlateBTriggered = true
        if (A := Agent?):
            StatusHUD.Show(A, PlateBMsg("Starboard plate locked in — waiting for port!"))
        else:
            StatusHUD.Show(PlateBMsg("Starboard plate locked in — waiting for port!"))
        CheckBothPlates(Agent)

    # --- AND gate check ---
    CheckBothPlates(Agent : ?agent) : void =
        # The AND: both flags must be true
        if (PlateATriggered = true and PlateBTriggered = true):
            # Fire the vault trigger — use the agent overload when we have one
            if (A := Agent?):
                VaultTrigger.Trigger(A)
            else:
                VaultTrigger.Trigger()
            StatusHUD.Show(VaultOpenMsg("VAULT OPEN! Grab the treasure, crew!"))
            # Reset flags so the puzzle can't re-fire (vault is already capped at 1)
            set PlateATriggered = false
            set PlateBTriggered = false

Line-by-Line Explanation

Lines What's happening
VaultTrigger.SetMaxTriggerCount(1) Caps the vault to fire exactly once — no cheesing the puzzle by re-triggering.
StatusHUD.SetDisplayTime(0.0) Makes the opening hint persist on screen until replaced.
StatusHUD.Show(BothPlatesMsg(...)) Broadcasts the hint to all players at round start.
PlateA.TriggeredEvent.Subscribe(OnPlateATriggered) Wires the plate's event to our handler. The handler receives ?agent (optional).
if (A := Agent?) Safely unwraps the optional agent — ?agent can be false if triggered by code.
StatusHUD.Show(A, PlateAMsg(...)) Shows a targeted message only on that player's HUD.
if (PlateATriggered = true and PlateBTriggered = true) The AND gate — both conditions must hold.
VaultTrigger.Trigger(A) / VaultTrigger.Trigger() Fires the vault door device, with or without an agent.

Common patterns

Pattern 1 — OR gate: captain's override OR crew plates

The captain can open the vault alone via a secret lever (OverridePlate), OR the two-crew AND gate succeeds. This uses or to combine two failable checks.

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

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

# OR gate: override plate alone is enough, OR both crew plates
dock_or_gate := class(creative_device):

    @editable
    OverridePlate : trigger_device = trigger_device{}

    @editable
    CrewPlateA : trigger_device = trigger_device{}

    @editable
    CrewPlateB : trigger_device = trigger_device{}

    @editable
    VaultTrigger : trigger_device = trigger_device{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

    var OverrideReady : logic = false
    var CrewAReady : logic = false
    var CrewBReady : logic = false

    OnBegin<override>()<suspends> : void =
        VaultTrigger.SetMaxTriggerCount(1)
        OverridePlate.TriggeredEvent.Subscribe(OnOverride)
        CrewPlateA.TriggeredEvent.Subscribe(OnCrewA)
        CrewPlateB.TriggeredEvent.Subscribe(OnCrewB)

    OnOverride(Agent : ?agent) : void =
        set OverrideReady = true
        CheckOrGate(Agent)

    OnCrewA(Agent : ?agent) : void =
        set CrewAReady = true
        CheckOrGate(Agent)

    OnCrewB(Agent : ?agent) : void =
        set CrewBReady = true
        CheckOrGate(Agent)

    CheckOrGate(Agent : ?agent) : void =
        # OR gate: captain override alone, OR both crew plates
        if (OverrideReady = true or (CrewAReady = true and CrewBReady = true)):
            if (A := Agent?):
                VaultTrigger.Trigger(A)
                StatusHUD.Show(A, OverrideMsg("Vault breached! Well played, captain."))
            else:
                VaultTrigger.Trigger()
                StatusHUD.Show(CrewMsg("Vault open — crew effort wins the day!"))
            set OverrideReady = false
            set CrewAReady = false
            set CrewBReady = false

Pattern 2 — Querying trigger state with GetTriggerCountRemaining and SetResetDelay

After the vault fires, display how many uses remain on a secondary alarm trigger, and set a cooldown before it can fire again. This covers GetTriggerCountRemaining, GetMaxTriggerCount, and SetResetDelay.

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

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

# Shows trigger stats and sets a reset delay on an alarm trigger
dock_alarm_stats := class(creative_device):

    @editable
    AlarmTrigger : trigger_device = trigger_device{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        # Allow the alarm to fire up to 3 times, with a 5-second cooldown between fires
        AlarmTrigger.SetMaxTriggerCount(3)
        AlarmTrigger.SetResetDelay(5.0)

        AlarmTrigger.TriggeredEvent.Subscribe(OnAlarmFired)

    OnAlarmFired(Agent : ?agent) : void =
        MaxCount := AlarmTrigger.GetMaxTriggerCount()
        Remaining := AlarmTrigger.GetTriggerCountRemaining()
        ResetDelay := AlarmTrigger.GetResetDelay()
        # Build a status string from the live device values
        # (Remaining and MaxCount are int; ResetDelay is float)
        # Show a timed message — 4 seconds, then auto-hide
        StatusHUD.Show(AlarmMsg("Alarm fired! Cooldown active. Check the dock."), ?DisplayTime := 4.0)

Pattern 3 — ClearAllMessages and HideMessageEvent

When the round ends (simulated here by a reset trigger), clear every queued HUD message and subscribe to HideMessageEvent to log when a message disappears from any player's screen.

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

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

# Clears HUD messages on a reset trigger and reacts to HideMessageEvent
dock_hud_cleanup := class(creative_device):

    @editable
    ResetTrigger : trigger_device = trigger_device{}

    @editable
    StatusHUD : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        ResetTrigger.TriggeredEvent.Subscribe(OnReset)
        StatusHUD.HideMessageEvent.Subscribe(OnMessageHidden)

    OnReset(Agent : ?agent) : void =
        # Wipe every queued message for all players
        StatusHUD.ClearAllMessages()
        # Re-enable the trigger so the reset can fire again
        ResetTrigger.Enable()

    OnMessageHidden(HideAgent : agent) : void =
        # Fires each time a message is hidden from a specific agent's screen
        # Show a brief confirmation only to that agent
        StatusHUD.Show(HideAgent, ClearedMsg("HUD cleared — new round incoming!"), ?DisplayTime := 2.0)

Gotchas

1. ?agent is NOT agent — always unwrap it

TriggeredEvent on trigger_device hands your handler a ?agent (optional agent). If you pass it directly to StatusHUD.Show(Agent, ...) the compiler rejects it — Show wants a plain agent. Unwrap first:

if (A := Agent?):
    StatusHUD.Show(A, MyMsg("Hello, pirate!"))
else:
    StatusHUD.Show(MyMsg("Hello, everyone!"))

2. messagestring — use a <localizes> function

Methods like SetText, Show(Message:message), and Show(Agent, Message:message) require a message value. You cannot pass a raw string literal or use a fictional StringToMessage. Declare a localizer at file scope:

MyText<localizes>(S : string) : message = "{S}"
// then call:
StatusHUD.SetText(MyText("Dock is clear!"))

3. and/or in if guards are failable combinators, not boolean operators

and fails the whole condition if either side fails. or short-circuits to the first success. This means:

# WRONG — logic variables are not failable by themselves:
if (PlateATriggered and PlateBTriggered):   # compile error

# CORRECT — compare to a concrete value:
if (PlateATriggered = true and PlateBTriggered = true):

4. SetMaxTriggerCount clamps to [0, 20]

Passing a value above 20 silently clamps to 20. Use 0 for unlimited. Always call GetMaxTriggerCount() after setting if you need to verify the clamped result.

5. int and float don't auto-convert

SetResetDelay takes a float; SetMaxTriggerCount takes an int. Passing 5 where 5.0 is expected (or vice-versa) is a compile error. Always match the literal type to the parameter type.

6. @editable fields MUST be declared inside the class body

A bare VaultTrigger.Trigger() at file scope with no class declaration fails with Unknown identifier. Every device reference must be an @editable field of a class(creative_device), and all logic must live in OnBegin or class-scope methods.

Guides & scripts that use trigger_device

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

Build your own lesson with trigger_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 →