Overview
The trigger_device solves a deceptively common problem: "how do I fire a cinematic (or any device) from Verse code AND from in-world events, with full control over timing, limits, and delays?"
Unlike a button_device (which requires a player to walk up and press it) or a cinematic_sequence_device (which plays the movie), the trigger is a pure relay. It:
- Fires
TriggeredEventthat any Verse handler can subscribe to. - Can be called from code with
Trigger()orTrigger(Agent), so you control when and who fires it. - Supports a max trigger count (great for one-shot boss intros), a reset delay (cooldown between fires), and a transmit delay (lag before downstream devices hear about it).
- Can be
Enabled /Disabled at runtime to gate access.
Reach for trigger_device whenever you need a programmable, rate-limited, chainable event source — especially as the bridge between a cinematic_sequence_device and the rest of your game logic.
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. |
Walkthrough
Scenario: The Vault Door Cinematic
A player steps on a pressure-plate trigger in the world. Your Verse device:
- Receives the event.
- Fires a boss-intro cinematic via
cinematic_sequence_device. - Uses a second
trigger_device(the EndTrigger) to signal downstream devices (open the vault door, spawn enemies) after a transmit delay. - The intro can only play once — after that the chain is locked.
Place two trigger_device instances and one cinematic_sequence_device in your level, then wire up this device:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# vault_cinematic_chain — place this creative_device in your level.
# Wire:
# PlateTrigger -> the trigger_device the pressure plate activates
# CinematicDevice -> the cinematic_sequence_device for the boss intro
# EndTrigger -> a trigger_device that opens the vault / spawns enemies
vault_cinematic_chain := class(creative_device):
# The trigger the pressure plate (or any in-world event) fires.
@editable
PlateTrigger : trigger_device = trigger_device{}
# The cinematic that plays when the player reaches the vault.
@editable
CinematicDevice : cinematic_sequence_device = cinematic_sequence_device{}
# Fires downstream (opens vault door, spawns enemies) after the cinematic.
@editable
EndTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# --- Configure the plate trigger ---
# Allow it to fire exactly once (boss intro is a one-shot event).
PlateTrigger.SetMaxTriggerCount(1)
# No reset delay needed — it can only fire once anyway.
PlateTrigger.SetResetDelay(0.0)
# --- Configure the end trigger ---
# Wait 2 seconds after the end trigger fires before
# downstream devices (vault door, spawner) hear about it.
# This gives the cinematic's final frame time to settle.
EndTrigger.SetTransmitDelay(2.0)
# Make sure both triggers are live at game start.
PlateTrigger.Enable()
EndTrigger.Enable()
# Subscribe: when the plate fires, run OnPlateTriggered.
PlateTrigger.TriggeredEvent.Subscribe(OnPlateTriggered)
# Subscribe: when the cinematic finishes, fire the end chain.
CinematicDevice.StoppedEvent.Subscribe(OnCinematicStopped)
# Called when the pressure plate trigger fires.
# Agent is ?agent because the trigger may fire without a player.
OnPlateTriggered(Agent : ?agent) : void =
# Lock the plate immediately so no one else can re-fire.
PlateTrigger.Disable()
# Play the cinematic for everyone (no agent required in this mode).
CinematicDevice.Play()
# Called when the cinematic sequence reaches its end and stops.
OnCinematicStopped(Unused : tuple()) : void =
# Fire the end trigger — the 2-second transmit delay means
# the vault door and spawner activate 2 s after this call.
EndTrigger.Trigger()```
### Line-by-line explanation
| Line(s) | What it does |
|---|---|
| `PlateTrigger.SetMaxTriggerCount(1)` | Clamps the plate to fire exactly once. Pass `0` for unlimited. |
| `PlateTrigger.SetResetDelay(0.0)` | No cooldown — irrelevant for a one-shot, but shown for clarity. |
| `EndTrigger.SetTransmitDelay(2.0)` | Downstream devices hear the signal 2 s after `Trigger()` is called. |
| `PlateTrigger.Enable()` | Ensures the trigger is active even if it was disabled in the editor. |
| `PlateTrigger.TriggeredEvent.Subscribe(OnPlateTriggered)` | Hooks our handler. The event sends `?agent`. |
| `CinematicDevice.StoppedEvent.Subscribe(OnCinematicStopped)` | Hooks the cinematic's own stopped event (sends `tuple()`). |
| `OnPlateTriggered(Agent : ?agent)` | Handler signature matches `listenable(?agent)`. |
| `PlateTrigger.Disable()` | Extra safety — even though max count is 1, disabling prevents any code path re-firing it. |
| `CinematicDevice.Play()` | Starts the cutscene for all players. |
| `EndTrigger.Trigger()` | Fires the relay; the 2-second transmit delay is already baked in. |
## Common patterns
### Pattern 1 — Trigger with a specific agent (player-gated cinematic)
Only the player who stepped on the plate sees their personal intro cinematic. We unwrap the optional agent before calling `Trigger(Agent)`.
```verse
using { /Fortnite.com/Devices }
# player_gated_cinematic — fires the cinematic only for the triggering player.
player_gated_cinematic := class(creative_device):
@editable
PlateTrigger : trigger_device = trigger_device{}
@editable
CinematicDevice : cinematic_sequence_device = cinematic_sequence_device{}
# A relay trigger that carries the agent identity downstream.
@editable
RelayTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
PlateTrigger.TriggeredEvent.Subscribe(OnPlateTriggered)
OnPlateTriggered(MaybeAgent : ?agent) : void =
# Unwrap the optional — the plate may fire without a player.
if (A := MaybeAgent?):
# Play the cinematic attributed to this specific agent.
CinematicDevice.Play(A)
# Relay the trigger downstream, carrying the agent identity.
RelayTrigger.Trigger(A)
Pattern 2 — Cooldown gate (reset delay + remaining count HUD logic)
A challenge trigger that players can activate every 30 seconds, up to 5 times total. After each fire, print how many uses remain (useful for debug or a score board).
using { /Fortnite.com/Devices }
# challenge_trigger_gate — rate-limited, count-limited challenge activator.
challenge_trigger_gate := class(creative_device):
@editable
ChallengeTrigger : trigger_device = trigger_device{}
@editable
ChallengeSequence : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends> : void =
# Players can activate this challenge at most 5 times total.
ChallengeTrigger.SetMaxTriggerCount(5)
# After each activation, wait 30 seconds before it can fire again.
ChallengeTrigger.SetResetDelay(30.0)
ChallengeTrigger.Enable()
ChallengeTrigger.TriggeredEvent.Subscribe(OnChallengeTriggered)
OnChallengeTriggered(MaybeAgent : ?agent) : void =
# Play the challenge intro cinematic for everyone.
ChallengeSequence.Play()
# Read back how many uses are left (0 means unlimited, but
# we set 5 so this will count down 4, 3, 2, 1, 0).
Remaining := ChallengeTrigger.GetTriggerCountRemaining()
MaxCount := ChallengeTrigger.GetMaxTriggerCount()
ResetSecs := ChallengeTrigger.GetResetDelay()
# Use Remaining / MaxCount / ResetSecs in your own HUD/log logic here.
Pattern 3 — Enable / Disable to gate a cinematic behind a puzzle
The cinematic trigger starts disabled. Only after all puzzle switches are solved does Verse enable it, letting the player step on the plate to fire the victory cutscene.
using { /Fortnite.com/Devices }
# puzzle_gate_cinematic — cinematic unlocks only after all switches are solved.
puzzle_gate_cinematic := class(creative_device):
# This trigger starts disabled in the editor (Enabled on Game Start = false).
@editable
VictoryTrigger : trigger_device = trigger_device{}
@editable
VictorySequence : cinematic_sequence_device = cinematic_sequence_device{}
# Each puzzle switch fires one of these triggers when solved.
@editable
SwitchTriggerA : trigger_device = trigger_device{}
@editable
SwitchTriggerB : trigger_device = trigger_device{}
var SolvedCount : int = 0
TotalSwitches : int = 2
OnBegin<override>()<suspends> : void =
# The victory trigger is disabled until all switches are solved.
VictoryTrigger.Disable()
SwitchTriggerA.TriggeredEvent.Subscribe(OnSwitchSolved)
SwitchTriggerB.TriggeredEvent.Subscribe(OnSwitchSolved)
VictoryTrigger.TriggeredEvent.Subscribe(OnVictoryTriggered)
OnSwitchSolved(MaybeAgent : ?agent) : void =
set SolvedCount = SolvedCount + 1
if (SolvedCount >= TotalSwitches):
# All switches solved — unlock the victory trigger.
VictoryTrigger.Enable()
OnVictoryTriggered(MaybeAgent : ?agent) : void =
# Lock it again so the cutscene only plays once.
VictoryTrigger.Disable()
VictorySequence.Play()
Gotchas
1. TriggeredEvent sends ?agent, not agent
The event signature is listenable(?agent). Your handler must accept ?agent:
# CORRECT
OnTriggered(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# use A as a real agent
If you write (Agent : agent) the code will not compile.
2. SetMaxTriggerCount is clamped to [0, 20]
Values above 20 are silently clamped. 0 means unlimited. If you need more than 20 fires, manage the count yourself in Verse and call Disable() when done.
3. GetTriggerCountRemaining returns 0 when the limit is unlimited
Don't use GetTriggerCountRemaining() = 0 as a "no uses left" check — it also returns 0 when GetMaxTriggerCount() is 0 (unlimited). Always check GetMaxTriggerCount() first:
if (ChallengeTrigger.GetMaxTriggerCount() > 0):
Remaining := ChallengeTrigger.GetTriggerCountRemaining()
# now Remaining is meaningful
4. Transmit delay vs. reset delay — they are different clocks
- Reset delay (
SetResetDelay) — how long before this trigger can fire again. - Transmit delay (
SetTransmitDelay) — how long before downstream devices (linked in the editor or via Verse) hear that this trigger fired.
They run independently. A 5-second reset delay does not delay the transmit signal.
5. Trigger() from code bypasses in-world player requirements
If your trigger is configured in the editor to require a player to physically enter its zone, calling Trigger() from Verse will still fire TriggeredEvent — but with false (i.e., ?agent resolves to nothing). Always unwrap ?agent defensively.
6. cinematic_sequence_device.StoppedEvent sends tuple(), not ?agent
When you chain a cinematic's end to a trigger, subscribe with a handler that accepts tuple():
CinematicDevice.StoppedEvent.Subscribe(OnCinematicStopped)
# ...
OnCinematicStopped(Unused : tuple()) : void =
EndTrigger.Trigger()
Mixing this up with ?agent is a common compile error.