Reference Verse compiles

grant_effect_to_player: Buffs, Curses, and Glowing Shores

The **Grant Effect to Player** device silently hands a player a gameplay effect — a speed boost, low gravity, invincibility, or a curse — the moment they cross a threshold or step on a trigger. Pair it with a `trigger_device` to detect the footstep and a `hud_message_device` to tell the player what just happened, and you have a complete, juicy feedback loop. This article teaches you exactly how those three devices talk to each other in Verse, set on a glowing 2D cel-shaded island cove where pira

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

Overview

The Grant Effect to Player device is a no-code-required UEFN device you place in your level and configure in its Details panel. It applies a named gameplay effect (speed, jump, shield regen, etc.) to whichever player activates it. In Verse you don't call methods on the grant-effect device itself — instead you drive it by wiring a trigger_device to it via the device's Triggered By channel, or you call TriggerDevice.Trigger(Agent) in code to fire the channel that the grant-effect device is listening on.

The Verse side of this workflow is therefore:

  1. trigger_device — detects the player stepping on the enchanted tide-pool and fires TriggeredEvent.
  2. Your Verse script calls GrantTrigger.Trigger(Agent) to relay the agent to the grant-effect device (which is wired to that trigger in the editor).
  3. hud_message_device — shows a custom message so the player knows they've been blessed (or cursed).

Reach for this pattern whenever you want a location-based buff/debuff — a speed shrine, a cursed altar, a healing spring, or a pirate relic that grants low gravity.

API Reference

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):

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.

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.

vector3

3-dimensional vector with float components.

Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).

vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:

Walkthrough

The Scene

You're building a sun-drenched cel-shaded cove. A glowing tide-pool sits at the water's edge. When a player wades into it they receive the Speed Surge effect (configured on the Grant Effect to Player device in the editor) and a HUD message flashes: "Blessed by the Tide! Speed Surge active."

After 10 seconds the blessing fades and a second message tells the player it has worn off.

Device Setup in the Editor

  1. Place a Trigger Zone (trigger_device) over the tide-pool. Set Trigger Delay to 0.
  2. Place a Grant Effect to Player device nearby. In its Details panel choose your effect (e.g. Speed Surge) and set Duration to 10 s.
  3. Wire the Grant Effect device's Triggered By channel to the GrantRelay trigger_device you'll reference in Verse.
  4. Place a HUD Message device. Set Target to Specific Player.
  5. Place a second HUD Message device for the expiry message.
  6. Drag your tide_pool_effect_manager Verse device into the level and assign all four devices in the Details panel.

The Verse Device

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

# Localized message helpers — message params require <localizes>
TideBlessing<localizes>(S : string) : message = "{S}"
TideExpired<localizes>(S : string) : message = "{S}"

# tide_pool_effect_manager
# Detects a player entering the enchanted tide-pool, relays the agent
# to the Grant Effect to Player device via GrantRelay, and shows HUD
# feedback for the duration of the effect.
tide_pool_effect_manager := class(creative_device):

    # The trigger zone the player physically walks into (the tide-pool collider).
    @editable TidePoolTrigger : trigger_device = trigger_device{}

    # A second trigger_device wired to the Grant Effect to Player device
    # in the editor. Calling Trigger(Agent) on this fires the grant.
    @editable GrantRelay : trigger_device = trigger_device{}

    # HUD message shown when the effect is granted.
    @editable BlessingHUD : hud_message_device = hud_message_device{}

    # HUD message shown when the effect expires.
    @editable ExpiredHUD : hud_message_device = hud_message_device{}

    # How long (seconds) the effect lasts — match the Grant Effect device setting.
    @editable EffectDuration : float = 10.0

    OnBegin<override>()<suspends> : void =
        # Each player may only receive the blessing once per visit;
        # set the tide-pool trigger to fire once then reset after the
        # effect duration so it can bless the next player.

        # Subscribe to the tide-pool trigger.
        TidePoolTrigger.TriggeredEvent.Subscribe(OnPlayerEntersTidePool)

        # Also subscribe to the grant relay so we can log/react when
        # the effect is actually dispatched (covers code-triggered path).
        GrantRelay.TriggeredEvent.Subscribe(OnEffectGranted)

    # Called when a player steps into the tide-pool zone.
    # MaybeAgent is ?agent — unwrap before use.
    OnPlayerEntersTidePool(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            # Relay the agent to the Grant Effect to Player device.
            GrantRelay.Trigger(Agent)

            # Show the blessing message on that player's screen.
            BlessingHUD.Show(Agent, TideBlessing("Blessed by the Tide! Speed Surge active."),
                ?DisplayTime := EffectDuration)

            # Schedule the expiry message on a background fiber.
            spawn { ShowExpiredMessage(Agent) }

    # Called when the grant relay fires (confirms the effect was sent).
    OnEffectGranted(MaybeAgent : ?agent) : void = {
        # Nothing extra needed here — the Grant Effect device handles the rest.
        # This handler is a good place to add scoring or analytics later.
    }

    # Waits for the effect duration then shows the expiry message.
    ShowExpiredMessage(Agent : agent)<suspends> : void =
        Sleep(EffectDuration)
        ExpiredHUD.Show(Agent, TideExpired("The Tide's blessing has faded."),
            ?DisplayTime := 3.0)```

### Line-by-Line Explanation

| Lines | What's happening |
|---|---|
| `TideBlessing<localizes>` / `TideExpired<localizes>` | Verse requires `message` values to be declared with `<localizes>`. There is no `StringToMessage` — this is the correct pattern. |
| `@editable TidePoolTrigger` | The physical collider the player walks into. Declared as a field so UEFN can wire it in the Details panel. |
| `@editable GrantRelay` | A second trigger_device whose *Triggered By* channel is wired to the Grant Effect to Player device in the editor. Calling `Trigger(Agent)` on it passes the agent through to the grant device. |
| `SetMaxTriggerCount(1)` | Prevents the tide-pool from spamming the effect if the player stands in it. |
| `SetResetDelay(EffectDuration)` | Resets the trigger after the effect wears off so the next player can be blessed. |
| `TriggeredEvent.Subscribe(OnPlayerEntersTidePool)` | Hooks our handler. The event sends `?agent` — we unwrap it with `if (Agent := MaybeAgent?):`. |
| `GrantRelay.Trigger(Agent)` | The key call — fires the relay trigger with the specific agent, which the Grant Effect device receives and applies the effect to. |
| `BlessingHUD.Show(Agent, ..., ?DisplayTime := EffectDuration)` | Shows a custom message on that player's screen for exactly as long as the effect lasts. |
| `spawn { ShowExpiredMessage(Agent) }` | Launches a background fiber so the main handler returns immediately while the timer runs. |
| `Sleep(EffectDuration)` | Suspends the fiber for the effect duration, then shows the expiry message. |

---

## Common Patterns

### Pattern 1 — One-Time Relic (SetMaxTriggerCount)

A pirate relic on a clifftop can only bless **one** player per match. After it fires, disable the trigger entirely.

```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

RelicMessage<localizes>(S : string) : message = "{S}"

pirate_relic_manager := class(creative_device):

    @editable RelicTrigger : trigger_device = trigger_device{}
    @editable GrantRelay   : trigger_device = trigger_device{}
    @editable RelicHUD     : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        # Only one player may ever claim the relic.
        RelicTrigger.SetMaxTriggerCount(1)
        RelicTrigger.TriggeredEvent.Subscribe(OnRelicClaimed)

    OnRelicClaimed(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            GrantRelay.Trigger(Agent)
            RelicHUD.Show(Agent,
                RelicMessage("You claimed the Pirate Relic! Low Gravity granted."),
                ?DisplayTime := 5.0)
            # Disable the zone so no one else can trigger it.
            RelicTrigger.Disable()

Pattern 2 — Broadcast Buff with ClearAllMessages

A ship's cannon fires and all players on the lagoon receive a shield effect. Show a broadcast message, then clear it after 4 seconds.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

CannonMsg<localizes>(S : string) : message = "{S}"

lagoon_cannon_manager := class(creative_device):

    # Trigger wired to a button the captain presses.
    @editable CannonButton   : trigger_device = trigger_device{}

    # Relay wired to Grant Effect device (affects ALL players via device setting).
    @editable GrantRelay     : trigger_device = trigger_device{}

    # Broadcast HUD (target = All Players in device settings).
    @editable BroadcastHUD   : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        CannonButton.TriggeredEvent.Subscribe(OnCannonFired)

    OnCannonFired(MaybeAgent : ?agent) : void =
        # Trigger the grant relay for all players (no agent needed — device
        # is configured to affect all players).
        GrantRelay.Trigger()

        # Show broadcast message to everyone.
        BroadcastHUD.Show(CannonMsg("The Captain fires! All crew gain Shield Regen!"))

        # Clear the message after 4 seconds on a background fiber.
        spawn { ClearAfterDelay() }

    ClearAfterDelay()<suspends> : void =
        Sleep(4.0)
        BroadcastHUD.ClearAllMessages()

Pattern 3 — Transmit Delay for Dramatic Timing

A cursed altar on a dock has a 2-second transmit delay so the visual effect plays before the grant fires. Use SetTransmitDelay to control this from code.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

CurseMsg<localizes>(S : string) : message = "{S}"

cursed_altar_manager := class(creative_device):

    @editable AltarTrigger : trigger_device = trigger_device{}
    @editable GrantRelay   : trigger_device = trigger_device{}
    @editable CurseHUD     : hud_message_device = hud_message_device{}

    # Seconds to wait before the grant relay informs downstream devices.
    @editable TransmitDelaySecs : float = 2.0

    OnBegin<override>()<suspends> : void =
        # Apply a transmit delay so the altar's VFX plays first.
        GrantRelay.SetTransmitDelay(TransmitDelaySecs)

        # Confirm the delay was set (GetTransmitDelay is <transacts>).
        var Delay : float = GrantRelay.GetTransmitDelay()

        AltarTrigger.TriggeredEvent.Subscribe(OnAltarTouched)

    OnAltarTouched(MaybeAgent : ?agent) : void =
        if (Agent := MaybeAgent?):
            # Show the ominous warning immediately.
            CurseHUD.Show(Agent,
                CurseMsg("The altar stirs... a curse descends upon you!"),
                ?DisplayTime := 3.0)

            # Trigger the relay — the grant fires after TransmitDelaySecs.
            GrantRelay.Trigger(Agent)

Gotchas

1. You can't call methods on the Grant Effect to Player device directly

The Grant Effect to Player device has no Verse API surface — you cannot import it as a typed field. The correct pattern is to wire a trigger_device (your GrantRelay) to the Grant Effect device in the editor, then call GrantRelay.Trigger(Agent) from Verse. The relay fires the channel the grant device is listening on.

2. TriggeredEvent sends ?agent, not agent

TriggeredEvent is typed listenable(?agent). Your handler signature must be (MaybeAgent : ?agent) : void and you must unwrap with if (Agent := MaybeAgent?): before passing Agent anywhere. Forgetting the ? is a common compile error.

3. message is not a string

hud_message_device.Show(Agent, Message, ...) takes a message, not a raw string literal. Declare a <localizes> helper function:

MyText<localizes>(S : string) : message = "{S}"

Then call MyText("Your text here"). There is no StringToMessage function.

4. int and float do not auto-convert

SetMaxTriggerCount takes int; SetResetDelay / SetTransmitDelay / Sleep take float. Passing 10 where 10.0 is expected (or vice-versa) is a compile error. Always use the correct literal suffix (10 vs 10.0).

5. SetMaxTriggerCount clamps to [0, 20]

Values above 20 are silently clamped. Use 0 to mean unlimited. If you want a one-time trigger, pass 1.

6. @editable fields must be declared at class scope

You cannot declare a trigger_device inside OnBegin and expect UEFN to wire it. Every device reference must be an @editable field at the top of your class(creative_device) body.

7. spawn {} is required for async calls inside sync handlers

Event handlers like OnPlayerEntersTidePool are synchronous. Calling Sleep() directly inside them will cause a compile error because Sleep is <suspends>. Wrap any async follow-up in spawn { MyAsyncFunc(Agent) }.

Guides & scripts that use player

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

Build your own lesson with player

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 →