Random Loot Picker with Live Verse UI
Tutorial beginner compiles

Random Loot Picker with Live Verse UI

Updated beginner Code verified

What you'll learn

  • How to store options (like loot names) in a []string array.
  • How to pick a random index safely with Random.GetRandomInt.
  • How to read that element out of the array in a failure context.
  • How to get the player_ui with GetPlayerUI[] and display the result with a text_block widget and AddWidget.

How it works

  1. Define the pool. We create an array of string values representing possible rewards.
  2. Pick an index. Random.GetRandomInt(0, N) returns a uniformly random int. Because array indices run from 0 to Len - 1, we pass Len(Pool) - 1 as the high bound.
  3. Read the element. Array indexing (Pool[Index]) is fallible, so it must live in an if — that guarantees we never touch an out-of-range slot.
  4. Show it. GetPlayerUI[Player] fails if the player has no UI, so we bind it in an if too. We then build a text_block, call SetText with an interpolated message, and hand it to AddWidget.

A key correctness note: GetPlayerUI is declared <decides>, so it is called with square brackets [] inside a failure context. GetRandomInt is a plain <transacts> function that returns an int, so it is called with parentheses () and its value is captured — never bracketed.

Let's build it

Place a Button Device in your level and assign it to the LootButton field in the device's Details panel. Pressing the button rolls the loot and prints it on that player's screen.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Random }
using { /Verse.org }

# A device that rolls a random loot item and shows it in the player's UI.
my_loot_picker := class<concrete>(creative_device):

    # Assign a Button Device to this in the UEFN Details panel.
    @editable
    LootButton : button_device = button_device{}

    # The pool of possible rewards.
    LootPool : []string = array{"Gold Coin", "Magic Sword", "Health Potion", "Rare Gem"}

    OnBegin<override>()<suspends>: void =
        # Wire the button press to our handler. Device events do NOT need () before Subscribe.
        LootButton.InteractedWithEvent.Subscribe(OnLootButtonPressed)

    # Runs every time a player presses the button.
    OnLootButtonPressed(Agent : agent) : void =
        # An agent is only a player when it has a valid player_ui. GetPlayerUI is <decides>,
        # so we call it with [] inside this failure context and bind the result.
        if (PlayerUI := GetPlayerUI[player[Agent]]):
            # High bound is Len - 1 so the index is always in range. GetRandomInt returns an
            # int via () and is inclusive on both ends.
            MaxIndex := LootPool.Length - 1
            RandomIndex := Random.GetRandomInt(0, MaxIndex)

            # Array indexing is fallible: bind it in an if so an empty/short pool can't crash us.
            if (SelectedLoot := LootPool[RandomIndex]):
                # Build the widget and set its text via an interpolated message.
                LootText : text_block = text_block{}
                LootText.SetText(StringToMessage("You received: {SelectedLoot}!"))

                # Push the widget onto this player's screen.
                PlayerUI.AddWidget(LootText)
                Print("Player received: {SelectedLoot}")

    # Helper: turn a string into a message for SetText, which requires a message.
    StringToMessage<localizes>(Value : string) : message = "{Value}"

Try it yourself

  • Grow the pool. Add more strings to LootPool — no other code changes are needed, because Len - 1 scales automatically.
  • Shuffle instead of index. Swap the pick for Random.Shuffle(LootPool) and read element 0 to draw a random order without repeats across a session.
  • Weight the drops. Duplicate common items in the pool ("Gold Coin", "Gold Coin", "Rare Gem") so common loot appears more often.
  • Guard the empty case. Add an else branch after if (SelectedLoot := ...) that prints a warning, so an accidentally empty pool fails gracefully.

Recap

You combined two APIs to make loot feel alive: Random.GetRandomInt (called with () and its int captured) for the roll, and the Player UI API for feedback. The two critical Verse habits here are calling <decides> functions like GetPlayerUI[] and fallible array indexing inside if failure contexts, while calling ordinary <transacts> functions like GetRandomInt(...) with parentheses and inspecting their returned value.

Check your understanding

Test yourself with an interactive quiz and track your progress + earn XP — free for members.

Turn this into a guided course

Add Random Element Selection from Arrays in Verse to your free study plan — we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.

Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.

Comments

    Sign in to vote, comment, or suggest an edit. Sign in