Overview
A trigger_device is a relay: something bumps it (a player, a linked device, or your own Verse code) and it fires its TriggeredEvent. You subscribe a handler to that event and run whatever game logic you want. It also carries useful runtime controls — you can Enable/Disable it, cap how many times it can fire with SetMaxTriggerCount, read the remaining fires with GetTriggerCountRemaining, and tune timing with SetResetDelay / SetTransmitDelay.
The game problem we're solving: on a sunny 2D cel-shaded pirate cove, players run across a wooden dock plate to "grab" treasure. Each pirate should have their OWN running coin count. That's a classic use for a Verse map — [agent]int — where we add an entry the first time we see a player, then bump it on every later trigger. The trigger_device is the sensor; the map is the ledger.
Reach for a trigger_device whenever you want a physical spot or a code signal to kick off logic, and reach for a map whenever you need to remember something per player.
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):
vector3
3-dimensional vector with
floatcomponents.
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).
vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:
Walkthrough
Picture a dock plank on the cove. A trigger_device sits on it. When a pirate steps on, we look them up in our coin ledger. If they're not in the map yet, we add an entry for them; otherwise we increment their existing count. We also cap the plank so it can't be spammed forever, and stagger its reset.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
cove_treasure_ledger := class(creative_device):
# The dock plank sensor placed on the cove. Drag your trigger here in the editor.
@editable
DockPlank : trigger_device = trigger_device{}
# Optional: a message the whole crew can hear (localized text).
CoinMessage<localizes>(Count:int) : message = "Arrr! Your coin count is now {Count}"
# The per-player coin ledger. A map that starts empty.
var CoinLedger : [agent]int = map{}
OnBegin<override>()<suspends>:void =
# Cap the plank so it can only fire 20 times total, then rest 1s between fires.
DockPlank.SetMaxTriggerCount(20)
DockPlank.SetResetDelay(1.0)
DockPlank.Enable()
# React whenever a pirate steps on the plank.
DockPlank.TriggeredEvent.Subscribe(OnPlankStepped)
OnPlankStepped(Agent : ?agent) : void =
# The event may fire with no agent (e.g. code-triggered). Unwrap safely.
if (Pirate := Agent?):
AddOrBumpCoins(Pirate)
AddOrBumpCoins(Pirate : agent) : void =
# Look the pirate up in the ledger.
if (Current := CoinLedger[Pirate]):
# They already have an entry — bump it.
if (CoinLedger[Pirate] = Current + 1):
Print(CoinMessage(Current + 1))
else:
# First time we see them — ADD A NEW MAP ENTRY starting at 1.
if (CoinLedger[Pirate] = 1):
Print(CoinMessage(1))```
**Line by line:**
- `@editable DockPlank : trigger_device` — you MUST declare the placed device as an editable field, then drag the real trigger onto it in the editor. A bare `trigger_device{}.Trigger()` would fail with 'Unknown identifier'.
- `var CoinLedger : [agent]int = map{}` — an empty map keyed by `agent`. This is our ledger.
- In `OnBegin`, `SetMaxTriggerCount(20)` clamps how many times the plank can fire; `SetResetDelay(1.0)` forces a one-second cooldown; `Enable()` turns it on.
- `DockPlank.TriggeredEvent.Subscribe(OnPlankStepped)` wires the event to our method. `TriggeredEvent` is a `listenable(?agent)`, so the handler receives `?agent`.
- `if (Pirate := Agent?)` unwraps the optional. If the trigger fired without an agent, we skip.
- `if (Current := CoinLedger[Pirate])` — a map lookup **succeeds** if the key exists. If it does, we `set CoinLedger[Pirate] = Current + 1`. If it fails (`else`), we **add a fresh entry** with `set CoinLedger[Pirate] = 1`. That `set ...[key] = value` on a missing key is exactly how you *add* a map entry in Verse.
## Common patterns
**1. Code-trigger the plank and read remaining fires.** Sometimes a cutscene or another device should fire the plank for a specific pirate. Use the `Trigger(Agent)` overload, then check how many fires are left with `GetTriggerCountRemaining`.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
cove_code_trigger := class(creative_device):
@editable
DockPlank : trigger_device = trigger_device{}
@editable
Cannon : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
DockPlank.SetMaxTriggerCount(5)
# When the cannon fires, fire the plank for that same pirate.
Cannon.TriggeredEvent.Subscribe(OnCannonFired)
OnCannonFired(Agent : ?agent) : void =
if (Pirate := Agent?):
DockPlank.Trigger(Pirate)
Remaining := DockPlank.GetTriggerCountRemaining()
Print("Plank fires left: {Remaining}")
2. Disable the plank once the treasure is claimed, and read timing back. Read the reset delay you configured, then shut the plank off so no one else can grab.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
cove_close_plank := class(creative_device):
@editable
DockPlank : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
DockPlank.SetResetDelay(2.5)
DockPlank.SetTransmitDelay(0.5)
DockPlank.Enable()
DockPlank.TriggeredEvent.Subscribe(OnClaimed)
OnClaimed(Agent : ?agent) : void =
Delay := DockPlank.GetResetDelay()
Transmit := DockPlank.GetTransmitDelay()
Print("Reset {Delay}s, transmit {Transmit}s — treasure claimed, closing plank.")
DockPlank.Disable()
3. A no-limit relay that forwards to a linked device. Set the max count to 0 for unlimited fires, then just relay every step onward by triggering another device.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_relay := class(creative_device):
@editable
ShoreSensor : trigger_device = trigger_device{}
@editable
LighthouseRelay : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
ShoreSensor.SetMaxTriggerCount(0) # 0 = no limit
Max := ShoreSensor.GetMaxTriggerCount()
ShoreSensor.Enable()
ShoreSensor.TriggeredEvent.Subscribe(OnShoreStep)
OnShoreStep(Agent : ?agent) : void =
if (Pirate := Agent?):
LighthouseRelay.Trigger(Pirate)
else:
LighthouseRelay.Trigger()
Gotchas
TriggeredEventhands you a?agent, not anagent. Always unwrap withif (Pirate := Agent?):before using it. Code-triggered fires can arrive with no agent.- Adding vs updating a map entry is the same
setsyntax.set CoinLedger[Pirate] = 1adds the key if it's missing and overwrites it if it exists. Guard with a lookup (if (Current := CoinLedger[Pirate])) when you want different behavior for new vs existing pirates. - A map field must be
varto change it.var CoinLedger : [agent]int = map{}— withoutvaryou can'tsetinto it. SetMaxTriggerCountis clamped to [0,20]. Passing0means unlimited; passing 100 quietly clamps to 20.messageparams need localized text, not a raw string. DeclareCoinMessage<localizes>(Count:int):message = "...{Count}"and callCoinMessage(3). There is noStringToMessage.- You cannot call a bare device.
trigger_device{}.Enable()fails; the device must be an@editablefield wired to a placed device in the editor. - No int↔float auto-convert.
SetResetDelaytakes afloat(1.0), whileSetMaxTriggerCounttakes anint(20). Mixing them without the right literal won't compile.