Overview
A map in Verse is written [key]value — a lookup table that pairs each key with a value. Think of it as the island's clipboard: [agent]int remembers a number for every player, [string]message remembers text under a name. The empty type false, function types, and non-<unique> classes cannot be keys, but agent, int, string, and float all can.
The game problem it solves: devices are stateless about individuals. A button fires InteractedWithEvent and hands you which agent pressed it — but the button itself doesn't remember that this is Jade's third press. A map does. You reach for a map any time you need "one value per player" or "look this thing up fast by name."
In this article we build a coconut cove: a button on the pirate dock that each player smacks to crack coconuts. A [agent]int map tallies each player's personal count, a HUD message device shows them their running score, and a trigger device fires a celebration once anyone reaches the target. We use the button's InteractedWithEvent, the HUD device's Show/SetText, and the trigger's Trigger/TriggeredEvent — the map is the glue holding per-player memory together.
API Reference
value
Full public surface, resolved verbatim from the live Epic digest (UnrealEngine.digest.verse).
value<native><public> := class:
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. |
button_device
Used to create a button which can trigger other devices when an agent interacts with it.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
button_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
InteractedWithEvent |
InteractedWithEvent<public>:listenable(agent) |
Signaled when an agent successfully interacts with the button for GetInteractionTime seconds. Sends the agent that interacted with the button. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
SetInteractionText |
SetInteractionText<public>(Text:message):void |
Sets the text that displays when an agent is close to this button and looks at it. Text is limited to 64 characters. |
SetInteractionTime |
SetInteractionTime<public>(Time:float):void |
Sets the duration of the interaction required to activate this device (in seconds). |
GetInteractionTime |
GetInteractionTime<public>()<transacts>:float |
Returns the duration of the interaction required to activate this device (in seconds). |
SetMaxTriggerCount |
SetMaxTriggerCount<public>(MaxCount:int):void |
Sets the maximum amount of times this button can be interacted with before it will be disabled. * MaxCount must be between 0 and 10000. * 0 indicates no limit on trigger count. |
GetMaxTriggerCount |
GetMaxTriggerCount<public>()<transacts>:int |
Returns the maximum amount of times this button can be interacted with before it will be disabled. * GetTriggerMaxCount will be between 0 and 10000. * 0 indicates no limit on trigger count. |
GetTriggerCountRemaining |
GetTriggerCountRemaining<public>()<transacts>:int |
Returns the number of times that this button can still be interacted with before it will be disabled. Will return 0 if GetMaxTriggerCount is unlimited. |
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: a 2D cel-shaded lagoon. A wooden Crack Coconut button sits on the dock. Every press adds one to the pressing player's tally stored in a [agent]int map. Their new count is pushed to their HUD. When a player hits 5, we fire a trigger device that (in the editor) is wired to fireworks over the cove.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
coconut_cove := class(creative_device):
# The dock button players smack to crack a coconut.
@editable
CrackButton : button_device = button_device{}
# Shows each player their personal coconut count.
@editable
CountHud : hud_message_device = hud_message_device{}
# Fires the fireworks when someone reaches the goal.
@editable
CelebrationTrigger : trigger_device = trigger_device{}
# The island's memory: one coconut tally per player.
var Coconuts : [agent]int = map{}
# Localized text helper — message params need this, not a raw string.
CoconutText<localizes>(Count:int):message = "You cracked {Count} coconuts!"
OnBegin<override>()<suspends>:void =
# Give players a clear prompt on the button.
CrackButton.SetInteractionText(CoconutText(0))
# React each time a player presses the button.
CrackButton.InteractedWithEvent.Subscribe(OnCrack)
# React when the celebration actually fires.
CelebrationTrigger.TriggeredEvent.Subscribe(OnCelebrate)
OnCrack(Agent:agent):void =
# Read this player's current count, defaulting to 0 if new.
Current := GetCount(Agent)
NewCount := Current + 1
# Store the updated value back into the map under this agent's key.
if (set Coconuts[Agent] = NewCount):
# Push their fresh personal count to the HUD.
CountHud.SetText(CoconutText(NewCount))
CountHud.Show(Agent)
# Hit the goal? Light up the cove.
if (NewCount >= 5):
CelebrationTrigger.Trigger(Agent)
# Helper: safely look up a count, returning 0 when the key is absent.
GetCount(Agent:agent)<transacts>:int =
if (Found := Coconuts[Agent]):
return Found
return 0
OnCelebrate(MaybeAgent:?agent):void =
# TriggeredEvent hands a ?agent — unwrap before use.
if (A := MaybeAgent?):
CountHud.Show(A, CoconutText(5), ?DisplayTime := 4.0)
Line by line:
var Coconuts : [agent]int = map{}— declares an empty mutable map. The key type isagent(the player), the value type isint(their tally).varmakes it reassignable so we can update entries.CoconutText<localizes>(Count:int):message— the button'sSetInteractionTextand the HUD'sSetTextboth take amessage, which must be a localized value. This function factory produces one. There is noStringToMessage.- In
OnBegin, we set the button prompt, thenSubscribeour two handler methods. Event handlers are ordinary methods at class scope — you subscribe them here, you don't define them inline. CrackButton.InteractedWithEventhands the handler a plainagent(not?agent), because the button always knows who pressed it. SoOnCrack(Agent:agent)receives it directly.GetCountdoes the map lookupCoconuts[Agent]inside anif— the lookup fails if the key isn't present yet, so we fall through toreturn 0for first-time crackers.set Coconuts[Agent] = NewCountwrites the value back. This mutation itself can fail syntactically in anif, so we guard it; on success we update the HUD.CelebrationTrigger.Trigger(Agent)fires the trigger as this agent, so downstream wiring knows who caused the fireworks.OnCelebrate(MaybeAgent:?agent)— the trigger'sTriggeredEventislistenable(?agent), so we get an optional agent. We unwrap withif (A := MaybeAgent?)before using it.
Common patterns
1. A [string]message map as a name-tag lookup for cove signposts. Different button, different value type — here we look up flavor text by a location name and push it to the HUD.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
signpost_reader := class(creative_device):
@editable
ReadButton : button_device = button_device{}
@editable
SignHud : hud_message_device = hud_message_device{}
Line<localizes>(S:string):message = "{S}"
# A map keyed by location name, valued by displayed message.
var Signs : [string]message = map{
"dock" => Line("Welcome to Sunny Dock!"),
"cove" => Line("Beware the Coconut Cove."),
"cliff" => Line("Clifftop lookout ahead.")
}
OnBegin<override>()<suspends>:void =
ReadButton.InteractedWithEvent.Subscribe(OnRead)
OnRead(Agent:agent):void =
# Look the message up by key; only show if the key exists.
if (Msg := Signs["cove"]):
SignHud.SetText(Msg)
SignHud.Show(Agent)
2. Using a [agent]logic map to gate a trigger so each player only fires it once. This covers the trigger's Trigger() (no-agent) form plus SetResetDelay.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
one_shot_lagoon := class(creative_device):
@editable
ArrivalPlate : trigger_device = trigger_device{}
@editable
HornTrigger : trigger_device = trigger_device{}
# Remembers whether each player has already sounded the horn.
var Sounded : [agent]logic = map{}
OnBegin<override>()<suspends>:void =
# Half-second cooldown so the horn can't double-fire.
HornTrigger.SetResetDelay(0.5)
ArrivalPlate.TriggeredEvent.Subscribe(OnArrive)
OnArrive(MaybeAgent:?agent):void =
if (A := MaybeAgent?):
# If no entry yet, this is their first arrival.
if (Sounded[A]):
# Already sounded — do nothing.
else if (set Sounded[A] = true):
HornTrigger.Trigger()
3. A [agent]int map with GetMaxTriggerCount to show remaining button presses. Covers SetMaxTriggerCount, GetTriggerCountRemaining, and a persistent HUD via SetDisplayTime.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
ration_dispenser := class(creative_device):
@editable
RationButton : button_device = button_device{}
@editable
RationHud : hud_message_device = hud_message_device{}
var Taken : [agent]int = map{}
Left<localizes>(N:int):message = "Rations left: {N}"
OnBegin<override>()<suspends>:void =
# Each player can press up to 3 times total.
RationButton.SetMaxTriggerCount(3)
RationHud.SetDisplayTime(0.0) # persistent
RationButton.InteractedWithEvent.Subscribe(OnTake)
OnTake(Agent:agent):void =
Prev := GetTaken(Agent)
if (set Taken[Agent] = Prev + 1):
Remaining := RationButton.GetTriggerCountRemaining()
RationHud.Show(Agent, Left(Remaining))
GetTaken(Agent:agent)<transacts>:int =
if (V := Taken[Agent]):
return V
return 0
Gotchas
- Map lookup is a failable expression.
Coconuts[Agent]fails (doesn't crash) when the key is absent. Always wrap reads inif (V := Map[Key]):and provide a default — never assume a key exists on first touch. set Map[Key] = Valuecan also appear in a failure context. Guard it withif (set Coconuts[Agent] = NewCount):as shown. The map must be declaredvarto be mutated.agentvs?agent. The button'sInteractedWithEventgives a bareagent; the trigger'sTriggeredEventgives an optional?agent. Unwrap the latter withif (A := MaybeAgent?):or you'll get a type error.messageis localized, not a string.SetText,SetInteractionText, and theShow(..., Message)overloads all wantmessage. Build one with a<localizes>function; there is noStringToMessage, and passing a raw"..."won't compile.- Bare device calls fail. You cannot call
CrackButton.Enable()unlessCrackButtonis an@editablefield on yourcreative_deviceclass and linked in the editor. A free-floatingbutton_device{}.Enable()throws 'Unknown identifier' at runtime linkage. - Non-comparable key types. You can't key a map by classes without
<unique>, function types, orfalse. Stick toagent,int,string,float,enumfor keys. - Persistent HUD needs
DisplayTime := 0.0. If you want a count to stay onscreen, eitherSetDisplayTime(0.0)on the device or pass?DisplayTime := 0.0toShow. A negative value means "use the device's set time."