Reference Verse compiles

Iterate an Array in Verse: Pirate Cove Patrol

Your pirate cove has five signal cannons along the dock — when a lookout steps on the crow's-nest trigger, every cannon fires in sequence and each crew member sees a personalised HUD warning. That's arrays plus iteration in action. In this article you'll learn how Verse's `for` expression walks an `[]trigger_device` array and a `[]hud_message_device` array to power that moment, then explore the supporting API calls that let you tune timing and limits.

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

Overview

An array in Verse is an ordered, fixed-size collection of values written with [] syntax — []trigger_device, []int, []string, etc. Iteration means visiting each element in turn so you can call a method on it, read it, or make a decision. In UEFN this pattern is everywhere:

  • Fire every cannon on a pirate ship when the alarm sounds.
  • Show a different HUD message to each player at round start.
  • Enable or disable a row of pressure plates based on game state.

You reach for array iteration whenever you have N things of the same type and want to act on all of them without copy-pasting code. The primary tool is the for expression; the primary pitfall is forgetting that array indexing is a failable context.

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.

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

Scenario — The Pirate Cove Alarm

Your cel-shaded lagoon island has a wooden dock stretching into a sunny cove. Five trigger_devices represent signal cannons bolted to the dock posts. One extra trigger sits on the crow's-nest platform — when a player steps on it the alarm fires:

  1. Every cannon trigger fires in sequence (with a short delay between each).
  2. Each cannon's HUD message device flashes a warning to ALL players.
  3. The crow's-nest trigger disables itself so it can only fire once.

Place in UEFN:

  • 1 × trigger_device named CrowsNestTrigger (crow's-nest pressure plate)
  • 5 × trigger_device named CannonTrigger0–4 (the dock cannons)
  • 5 × hud_message_device named CannonHUD0–4 (one per cannon, pre-configured with a warning text)
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# Localised helper — message params must be `message`, not raw string
CannonWarning<localizes>(S : string) : message = "{S}"

pirate_cove_alarm := class(creative_device):

    # The crow's-nest pressure plate that starts the alarm
    @editable
    CrowsNestTrigger : trigger_device = trigger_device{}

    # Five dock cannons — iterate this array to fire them all
    @editable
    CannonTriggers : []trigger_device = array{}

    # One HUD message device per cannon — parallel array, same indices
    @editable
    CannonHUDs : []hud_message_device = array{}

    # Seconds between each cannon firing
    @editable
    FireDelay : float = 0.4

    OnBegin<override>()<suspends> : void =
        # Allow the crow's-nest trigger to fire exactly once
        CrowsNestTrigger.SetMaxTriggerCount(1)

        # Subscribe: when a player steps on the crow's nest, run OnAlarmRaised
        CrowsNestTrigger.TriggeredEvent.Subscribe(OnAlarmRaised)

    # Called when the crow's-nest trigger fires.
    # TriggeredEvent sends ?agent, so the param is ?agent.
    OnAlarmRaised(MaybeAgent : ?agent) : void =
        # Disable the crow's nest so no second alarm can start
        CrowsNestTrigger.Disable()

        # Spawn a concurrent task so we can Sleep between cannon shots
        spawn { FireAllCannons() }

    # Fires each cannon in sequence with a delay, updating the matching HUD
    FireAllCannons()<suspends> : void =
        # Iterate the CannonTriggers array by index
        for (Index -> CannonTrigger : CannonTriggers):
            # Fire the cannon trigger (no agent — triggered through code)
            CannonTrigger.Trigger()

            # Show the matching HUD message if the parallel array has an entry
            if (HUD := CannonHUDs[Index]):
                # Override the device text at runtime with a dynamic message
                HUD.SetText(CannonWarning("CANNON {Index + 1} FIRED — TAKE COVER!"))
                HUD.Show()

            # Brief pause before the next cannon
            Sleep(FireDelay)

        # After all cannons have fired, clear every HUD after 3 seconds
        Sleep(3.0)
        for (HUD : CannonHUDs):
            HUD.Hide()

Line-by-line explanation

Lines What's happening
CannonTriggers : []trigger_device Declares an editable array of trigger devices. Wire them in the UEFN Details panel.
CannonHUDs : []hud_message_device Parallel array — CannonHUDs[0] belongs to CannonTriggers[0], etc.
SetMaxTriggerCount(1) Caps the crow's-nest trigger to one activation ever.
TriggeredEvent.Subscribe(OnAlarmRaised) Hooks the handler; the event signature is listenable(?agent).
OnAlarmRaised(MaybeAgent : ?agent) Matches the listenable(?agent) signature — we don't need the agent here so we don't unwrap it.
spawn { FireAllCannons() } Launches a suspending function without blocking OnAlarmRaised.
for (Index -> CannonTrigger : CannonTriggers) Index-value iteration: Index is int, CannonTrigger is trigger_device.
CannonTrigger.Trigger() Fires the cannon trigger through code (no agent).
if (HUD := CannonHUDs[Index]) Array indexing is failable — wrap in if to safely access the parallel array.
HUD.SetText(...) Replaces the device's configured text at runtime.
HUD.Show() Displays the message to all players.
for (HUD : CannonHUDs): HUD.Hide() Value-only iteration — no index needed when you just want every element.

Common patterns

Pattern 1 — Configure every trigger's reset delay from one array

You have a row of dock pressure plates that should reset at different speeds. Store the delays in a parallel []float and iterate both arrays together.

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

dock_plate_configurator := class(creative_device):

    @editable
    DockPlates : []trigger_device = array{}

    # One reset delay (seconds) per plate — must match DockPlates length
    @editable
    ResetDelays : []float = array{}

    OnBegin<override>()<suspends> : void =
        # Iterate by index so we can read the matching delay
        for (Index -> Plate : DockPlates):
            if (Delay := ResetDelays[Index]):
                Plate.SetResetDelay(Delay)
                # Also enable each plate in case they started disabled
                Plate.Enable()

What's new here: SetResetDelay and Enable — two more trigger API calls applied across the whole array in one loop.


Pattern 2 — Show a personalised HUD to a specific agent from a trigger event

When a player steps on the lagoon gate trigger, show them a personal message using Show(Agent, Message) and log how many triggers remain.

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

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

lagoon_gate_greeter := class(creative_device):

    @editable
    GateTrigger : trigger_device = trigger_device{}

    @editable
    WelcomeHUD : hud_message_device = hud_message_device{}

    # Array of extra triggers to disable once the gate opens
    @editable
    SideTriggers : []trigger_device = array{}

    OnBegin<override>()<suspends> : void =
        GateTrigger.SetMaxTriggerCount(5)
        GateTrigger.TriggeredEvent.Subscribe(OnGateTriggered)

    OnGateTriggered(MaybeAgent : ?agent) : void =
        # Unwrap the optional agent to show a targeted HUD message
        if (A := MaybeAgent?):
            Remaining := GateTrigger.GetTriggerCountRemaining()
            WelcomeHUD.Show(A, LagoonGreeting("Welcome, sailor! {Remaining} entries left."))

        # Disable all side triggers — value-only for loop, no index needed
        for (Side : SideTriggers):
            Side.Disable()

What's new here: GetTriggerCountRemaining() read at runtime, Show(Agent, Message) for a targeted HUD, and the ?agent unwrap pattern with if (A := MaybeAgent?).


Pattern 3 — Clear all HUD messages and re-enable triggers for a new round

At round reset, clear every HUD and re-enable every cannon trigger so the alarm can fire again.

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

cove_round_reset := class(creative_device):

    @editable
    ResetTrigger : trigger_device = trigger_device{}

    @editable
    CannonTriggers : []trigger_device = array{}

    @editable
    CannonHUDs : []hud_message_device = array{}

    OnBegin<override>()<suspends> : void =
        ResetTrigger.TriggeredEvent.Subscribe(OnRoundReset)

    OnRoundReset(MaybeAgent : ?agent) : void =
        # Clear all queued HUD messages in one call per device
        for (HUD : CannonHUDs):
            HUD.ClearAllMessages()

        # Re-enable every cannon and reset their trigger count limit
        for (Cannon : CannonTriggers):
            Cannon.SetMaxTriggerCount(0)   # 0 = unlimited
            Cannon.Enable()

What's new here: ClearAllMessages() on the HUD device, SetMaxTriggerCount(0) to restore unlimited firing, and Enable() to bring disabled triggers back online.

Gotchas

1. Array indexing is failable — always wrap in if

Writing CannonHUDs[Index] outside a failure context is a compile error. Always use if (HUD := CannonHUDs[Index]): or the access inside a for expression that already handles failure.

2. listenable(?agent) vs listenable(agent)

trigger_device.TriggeredEvent is listenable(?agent) — the agent is optional. Your handler must accept (MaybeAgent : ?agent). If you write (A : agent) the types won't match and the subscribe call won't compile. Unwrap with if (A := MaybeAgent?) before using A as a concrete agent.

3. message is not a string

HUD.SetText() and HUD.Show(Agent, Message) require a message value, not a raw string literal. Declare a <localizes> helper function:

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

Then call HUD.SetText(MyText("Fire!")). There is no StringToMessage function.

4. int and float don't auto-convert

SetResetDelay takes float. If you compute a delay as int you must write float(MyInt) to convert it. Passing a bare int literal like 2 works because integer literals are polymorphic, but a variable typed int will not silently coerce.

5. Parallel arrays must stay in sync

If CannonTriggers has 5 elements but CannonHUDs has only 4, CannonHUDs[4] fails silently (the if just skips). Wire all devices in the UEFN Details panel and double-check counts. Consider adding a length-check log in OnBegin during development.

6. spawn is required for suspending work inside an event handler

Event handlers (subscribed methods) are not suspending contexts. If you call Sleep or any <suspends> function directly inside the handler, it won't compile. Wrap the suspending work in spawn { MyFunc() } as shown in the walkthrough.

7. SetMaxTriggerCount clamps to [0, 20]

Passing a value above 20 silently clamps to 20. Use 0 for unlimited. Plan your alarm logic around this ceiling.

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 →