Reference Verse compiles

map key-value: Tracking Player State on a Sunny Cove

A Verse map ([key]value) is your island's memory: it lets you remember something about each player — how many coconuts they cracked, whether they've visited the cove — and react. In this bright cel-shaded lagoon we'll pair a map with buttons, triggers, and a HUD message device so every pirate gets their own live coconut counter.

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

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 is agent (the player), the value type is int (their tally). var makes it reassignable so we can update entries.
  • CoconutText<localizes>(Count:int):message — the button's SetInteractionText and the HUD's SetText both take a message, which must be a localized value. This function factory produces one. There is no StringToMessage.
  • In OnBegin, we set the button prompt, then Subscribe our two handler methods. Event handlers are ordinary methods at class scope — you subscribe them here, you don't define them inline.
  • CrackButton.InteractedWithEvent hands the handler a plain agent (not ?agent), because the button always knows who pressed it. So OnCrack(Agent:agent) receives it directly.
  • GetCount does the map lookup Coconuts[Agent] inside an if — the lookup fails if the key isn't present yet, so we fall through to return 0 for first-time crackers.
  • set Coconuts[Agent] = NewCount writes the value back. This mutation itself can fail syntactically in an if, 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's TriggeredEvent is listenable(?agent), so we get an optional agent. We unwrap with if (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 in if (V := Map[Key]): and provide a default — never assume a key exists on first touch.
  • set Map[Key] = Value can also appear in a failure context. Guard it with if (set Coconuts[Agent] = NewCount): as shown. The map must be declared var to be mutated.
  • agent vs ?agent. The button's InteractedWithEvent gives a bare agent; the trigger's TriggeredEvent gives an optional ?agent. Unwrap the latter with if (A := MaybeAgent?): or you'll get a type error.
  • message is localized, not a string. SetText, SetInteractionText, and the Show(..., Message) overloads all want message. Build one with a <localizes> function; there is no StringToMessage, and passing a raw "..." won't compile.
  • Bare device calls fail. You cannot call CrackButton.Enable() unless CrackButton is an @editable field on your creative_device class and linked in the editor. A free-floating button_device{}.Enable() throws 'Unknown identifier' at runtime linkage.
  • Non-comparable key types. You can't key a map by classes without <unique>, function types, or false. Stick to agent, int, string, float, enum for keys.
  • Persistent HUD needs DisplayTime := 0.0. If you want a count to stay onscreen, either SetDisplayTime(0.0) on the device or pass ?DisplayTime := 0.0 to Show. A negative value means "use the device's set time."

Guides & scripts that use value

Step-by-step tutorials that put this object to work.

Build your own lesson with value

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 →