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. message ≠ string — 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.