Reference Verse compiles

conditional_button_device: The Gated Button That Demands Payment

The Conditional Button is a specialized button that refuses to fire until the interacting player is carrying the right items. Where a plain button triggers for anyone, the Conditional Button checks your pockets first — perfect for locked vaults, toll gates, crafting stations, and treasure chests hidden in a sun-drenched cove. Wire it to Verse and you can dynamically change the cost, read how many items a player still needs, and react differently when they come up short.

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

Overview

The conditional_button_device is a button that only activates when the interacting agent is carrying a required quantity of one or more key items configured in the device's properties panel. It fires two events:

  • ActivatedEvent — the player had the goods; the button succeeded.
  • NotEnoughItemsEvent — the player tried but was short; nothing was consumed.

Reach for this device whenever you want a cost gate in front of an action: unlocking a clifftop cannon, boarding a ferry at the dock, opening a sunken-treasure chest in a cove, or trading fish for a weapon at a shore-side shop. Pair it with Verse to read item counts at runtime, change the required cost mid-game, or show a custom hint that tells the player exactly how many more items they need.

API Reference

conditional_button_device

Used to create a specialized button which can only be activated when agents are carrying specific items.

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

conditional_button_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
ActivatedEvent ActivatedEvent<public>:listenable(agent) Signaled when this device is activated. Sends the agent that activated this device.
NotEnoughItemsEvent NotEnoughItemsEvent<public>:listenable(agent) Signaled when this device fails to activate because agent didn't have the required items. Sends the agent that attempted to activate the device.

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.
Activate Activate<public>(Agent:agent):void Activates this device. Agent is used as the instigator of the action.
Toggle Toggle<public>(Agent:agent):void Toggles the conditional button state. Agent is used as the instigator of the action.
SetInteractionText SetInteractionText<public>(Text:message):void Sets the text that appears when agents approach the device. Text is limited to 150 characters and will revert back to default if empty.
SetInteractionTime SetInteractionTime<public>(Time:float):void Sets the time (in seconds) that an interaction with this device should take to complete.
GetInteractionTime GetInteractionTime<public>()<transacts>:float Returns the time (in seconds) that an interaction with this device will take to complete.
SetItemCountRequired SetItemCountRequired<public>(KeyItemIndex:int, Count:int):void Sets the quantity of a specific key item type that needs to be collected in order to activate the switch. KeyItemIndex ranges from 0 to number of key item types - 1.
GetItemCountRequired GetItemCountRequired<public>(KeyItemIndex:int)<transacts>:int Returns the total quantity of a specific key item type that needs to be collected in order to activate the switch.
GetRemainingItemCountRequired GetRemainingItemCountRequired<public>(KeyItemIndex:int)<transacts>:int Returns the remaining quantity of a specific key item type that needs to be collected in order to activate the switch.
SetItemScore SetItemScore<public>(KeyItemIndex:int, Score:int):void Sets the score to be awarded for a key item. KeyItemIndex ranges from 0 to number of key item types - 1.
GetItemScore GetItemScore<public>(KeyItemIndex:int)<transacts>:int Returns the score to be awarded for a key item.
GetItemCount GetItemCount<public>(Agent:agent, KeyItemIndex:int):int Returns how many items an Agent has of the item stored at KeyItemIndex.
HasAllItems HasAllItems<public>(Agent:agent)<transacts><decides>:void Returns if the Agent has all of the items required to interact with this Device.
IsHoldingItem IsHoldingItem<public>(Agent:agent)<transacts><decides>:void Returns if the Agent is currently holding any of the items stored in the Device.
IsHoldingItem IsHoldingItem<public>(Agent:agent, KeyItemIndex:int)<transacts><decides>:void Returns if the Agent is currently holding the item stored at KeyItemIndex.

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.

Walkthrough

Scenario — The Cove Treasure Chest

You've built a sun-drenched cove island. A glowing treasure chest sits on a wooden dock. Players must collect 3 Golden Doubloons (key item 0, configured in the device panel) and bring them to the chest to open it. When they succeed, a cinematic trigger fires and the chest opens. When they fall short, the button tells them exactly how many more coins they need.

Place these devices in your UEFN level:

  • conditional_button_device — the chest's interaction button (key item 0 = Golden Doubloon, count = 3)
  • trigger_device — fires the chest-open cinematic
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

# Localized helper so we can pass dynamic text as a `message`.
ChestPrompt<localizes>(S : string) : message = "{S}"

cove_treasure_chest_manager := class(creative_device):

    # The conditional button placed on the dock chest.
    @editable
    ChestButton : conditional_button_device = conditional_button_device{}

    # A trigger that fires the chest-open cinematic / prop animation.
    @editable
    ChestOpenTrigger : trigger_device = trigger_device{}

    # Key item index 0 = Golden Doubloon (set up in the device panel).
    DoubloonIndex : int = 0
    DoubloonCost  : int = 3

    OnBegin<override>()<suspends> : void =
        # ── Runtime configuration ──────────────────────────────────────
        # Enforce the cost in code so it's easy to tune from one place.
        ChestButton.SetItemCountRequired(DoubloonIndex, DoubloonCost)

        # Give the button a flavour-text prompt visible on approach.
        ChestButton.SetInteractionText(ChestPrompt("Open Treasure Chest"))

        # A 1-second hold makes it feel weighty — not an accidental tap.
        ChestButton.SetInteractionTime(1.0)

        # ── Event subscriptions ────────────────────────────────────────
        ChestButton.ActivatedEvent.Subscribe(OnChestOpened)
        ChestButton.NotEnoughItemsEvent.Subscribe(OnNotEnoughDoubloons)

        ChestButton.Enable()

    # Called when the player had all 3 doubloons and activated the button.
    OnChestOpened(Agent : agent) : void =
        # Fire the cinematic / prop-open trigger.
        ChestOpenTrigger.Trigger(Agent)

        # After the chest is looted, disable the button so it can't be
        # opened a second time.
        ChestButton.Disable()

    # Called when the player tried but didn't have enough doubloons.
    OnNotEnoughDoubloons(Agent : agent) : void =
        # Find out how many more coins this player still needs.
        Remaining := ChestButton.GetRemainingItemCountRequired(DoubloonIndex)

        # Update the prompt so the player sees a personalised hint.
        HintText := "Need {Remaining} more Doubloon(s)!"
        ChestButton.SetInteractionText(ChestPrompt(HintText))

Line-by-line explanation

Lines What's happening
SetItemCountRequired(0, 3) Tells the device at runtime that key item slot 0 requires exactly 3 items. Overrides whatever was set in the panel.
SetInteractionText(...) Shows custom flavour text when a player walks up to the chest. Accepts a message (localized value), not a raw string.
SetInteractionTime(1.0) Player must hold the interact key for 1 second — prevents accidental activations.
ActivatedEvent.Subscribe(OnChestOpened) Registers our handler; fires only when the player had all required items.
NotEnoughItemsEvent.Subscribe(OnNotEnoughDoubloons) Registers our "you're broke" handler.
ChestOpenTrigger.Trigger(Agent) Fires the cinematic trigger, passing the activating agent as instigator.
ChestButton.Disable() One-time chest — disables the button after a successful open.
GetRemainingItemCountRequired(0) Returns how many of item 0 the player still needs; used to build a personalised hint.

Common patterns

Pattern 1 — Dynamically raise the cost mid-game (escalating toll gate)

A toll booth on the clifftop road starts cheap and gets more expensive each time a player pays. Uses SetItemCountRequired and GetItemCountRequired together.

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

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

clifftop_toll_manager := class(creative_device):

    @editable
    TollButton : conditional_button_device = conditional_button_device{}

    # Key item index 0 = Toll Coin.
    TollItemIndex : int = 0

    OnBegin<override>()<suspends> : void =
        # Start at 1 coin.
        TollButton.SetItemCountRequired(TollItemIndex, 1)
        TollButton.SetInteractionText(TollPrompt("Pay Toll"))
        TollButton.Enable()
        TollButton.ActivatedEvent.Subscribe(OnTollPaid)

    OnTollPaid(Agent : agent) : void =
        # Read the current cost, then raise it by 1 for next time.
        CurrentCost := TollButton.GetItemCountRequired(TollItemIndex)
        NewCost     := CurrentCost + 1
        TollButton.SetItemCountRequired(TollItemIndex, NewCost)

        # Refresh the prompt so the next player sees the updated price.
        TollButton.SetInteractionText(TollPrompt("Pay Toll"))

Pattern 2 — Check whether a player is holding the key item before they even interact

A shore-side ferry gate uses HasAllItems (a <decides> function) to light up a green lamp the moment a player walks near, giving visual feedback before they press anything.

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

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

ferry_gate_manager := class(creative_device):

    @editable
    FerryButton : conditional_button_device = conditional_button_device{}

    # A trigger that turns on the green "ready" lamp prop.
    @editable
    GreenLampTrigger : trigger_device = trigger_device{}

    # A trigger that turns on the red "not ready" lamp prop.
    @editable
    RedLampTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends> : void =
        FerryButton.SetInteractionText(FerryPrompt("Board Ferry"))
        FerryButton.Enable()
        FerryButton.ActivatedEvent.Subscribe(OnBoarded)
        FerryButton.NotEnoughItemsEvent.Subscribe(OnBoardingFailed)

    # Utility called from game logic when a player approaches the gate.
    # (Wire this from a trigger_device's TriggeredEvent in a real setup.)
    CheckPlayerReadiness(Agent : agent) : void =
        # HasAllItems is a <decides> function — use it inside an if.
        if (FerryButton.HasAllItems[Agent]):
            GreenLampTrigger.Trigger(Agent)
        else:
            RedLampTrigger.Trigger(Agent)

    OnBoarded(Agent : agent) : void =
        FerryButton.Disable()

    OnBoardingFailed(Agent : agent) : void =
        RedLampTrigger.Trigger(Agent)

Pattern 3 — Temporarily toggle the button off during a cooldown

A dock cannon can only be fired once every 10 seconds. After activation the button is toggled off; a Sleep brings it back. Uses Toggle and Activate.

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

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

dock_cannon_manager := class(creative_device):

    @editable
    CannonButton : conditional_button_device = conditional_button_device{}

    @editable
    CannonTrigger : trigger_device = trigger_device{}

    CooldownSeconds : float = 10.0
    AmmoItemIndex   : int   = 0

    OnBegin<override>()<suspends> : void =
        CannonButton.SetItemCountRequired(AmmoItemIndex, 1)
        CannonButton.SetInteractionText(CannonPrompt("Fire Cannon"))
        CannonButton.SetInteractionTime(0.5)
        CannonButton.Enable()
        CannonButton.ActivatedEvent.Subscribe(OnCannonFired)

    OnCannonFired(Agent : agent) : void =
        CannonTrigger.Trigger(Agent)
        # Disable during cooldown, then re-enable.
        spawn:
            CooldownAndReenable(Agent)

    CooldownAndReenable(Agent : agent)<suspends> : void =
        # Toggle off immediately (button is currently enabled → becomes disabled).
        CannonButton.Toggle(Agent)
        CannonButton.SetInteractionText(CannonPrompt("Reloading..."))
        Sleep(CooldownSeconds)
        # Toggle back on.
        CannonButton.Toggle(Agent)
        CannonButton.SetInteractionText(CannonPrompt("Fire Cannon"))

Gotchas

1 — SetInteractionText requires a message, not a string

The parameter type is message (a localized value). You cannot pass a raw string literal or a string variable directly. Declare a localizes helper:

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

Then call ChestButton.SetInteractionText(MyPrompt("Open Chest")). There is no StringToMessage built-in.

2 — HasAllItems and IsHoldingItem are <decides> functions

They don't return a bool — they succeed or fail. Always call them inside an if expression:

if (ChestButton.HasAllItems[Agent]):
    # player is ready

Note the square brackets [] — required for failable (decides) calls.

3 — NotEnoughItemsEvent fires but items are NOT consumed

The device only consumes items on a successful ActivatedEvent. If you're updating UI or prompts in NotEnoughItemsEvent, don't assume any inventory change occurred.

4 — KeyItemIndex is 0-based and bounded by the panel configuration

If you call SetItemCountRequired(2, 5) but only configured 2 key item slots (indices 0 and 1) in the panel, the call is silently ignored at runtime. Always match your code indices to the number of key item types you set up in the device's Details panel.

5 — GetRemainingItemCountRequired is per-call, not reactive

It returns the remaining count at the moment you call it. If you want a live HUD counter, poll it on a timer or call it inside NotEnoughItemsEvent (which fires every failed attempt).

6 — Toggle uses the current enabled state

Toggle(Agent) flips enabled↔disabled. If you call it twice in quick succession (e.g., in a race condition with two players), the state may not be what you expect. Prefer explicit Enable() / Disable() when you need deterministic state.

7 — @editable fields are mandatory for placed devices

You cannot construct a conditional_button_device{} in code and expect it to exist in the world. Always declare it @editable and assign the placed device in the Details panel:

@editable
ChestButton : conditional_button_device = conditional_button_device{}

Guides & scripts that use conditional_button_device

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

Build your own lesson with conditional_button_device

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 →