Filter an Array: Still-Racing List

In this lesson you'll learn to

  • βœ“Build a new array of only the elements passing a test.

Build a new array of only the elements passing a test.

πŸ“– Reference & full walkthrough: Filter an Array: Still-Racing List

🧩 Your capstone piece: still_racing := racers filtered by not-finished


Overview

Picture a bright, 2D cel-shaded cove: a wooden dock stretches out over a sparkling lagoon, a pirate ship bobs offshore, and gulls wheel over the clifftop. When a wave of players rushes the dock, you often need to act on only some of them β€” the ones with full shields, the ones close enough to the treasure chest, the ones on the winning team.

That is what filtering an array solves. In Verse there is no special "filter device" β€” filtering is a language feature you use on the arrays that devices hand you. The workhorse is the for expression with a failable filter clause:

Survivors := for (P : AllPlayers, P.GetHealth() > 50.0) { P }

Each element is tested; if the filter fails, that element is skipped; the ones that pass are collected into a brand-new array. In this article we combine that with two real devices:

  • A trigger_device β€” we Trigger(Agent) it once per filtered player, and read GetTriggerCountRemaining() to gate how many can pass.
  • A hud_message_device β€” we Show(Agent, Message) a personal banner to each filtered player.

Reach for array filtering any time a device gives you a collection (all players, all FindCreativeObjectsWithTag objects, all event payloads) and you only want the subset that matches a rule.

API Reference

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.

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

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 scenario: A trigger sits at the end of the dock. When any player steps on it, we look at every player on the island, keep only those who are still alive with more than half health, and for each of those survivors we (1) flash them a personal "Welcome aboard!" HUD banner and (2) re-fire a second trigger for them β€” but only while GetTriggerCountRemaining() says there are boarding slots left.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/SpatialMath }

boarding_dock := class(creative_device):

    # The plate at the end of the dock a player steps on.
    @editable DockTrigger : trigger_device = trigger_device{}

    # Fires once per player who passes the filter (e.g. opens the gangplank).
    @editable BoardTrigger : trigger_device = trigger_device{}

    # Personal banner shown to each surviving player.
    @editable WelcomeHud : hud_message_device = hud_message_device{}

    # message helper: turns a plain string into a localized message.
    Banner<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends>:void =
        # React whenever a player steps on the dock trigger.
        DockTrigger.TriggeredEvent.Subscribe(OnDockStepped)

    OnDockStepped(Agent : ?agent) : void =
        # Get every player currently in the game.
        AllPlayers := GetPlayspace().GetPlayers()

        # FILTER: keep only living players with more than half health.
        # Each clause after the loop var is failable; failure skips the element.
        Survivors := for:
            P : AllPlayers
            Char := P.GetFortCharacter[]      # fails if no character -> skips
            Char.GetHealth() > 50.0           # fails if too hurt -> skips
        do:
            P

        # Now act ONLY on the filtered subset.
        for (Boarder : Survivors):
            # Flash a personal banner to this survivor.
            WelcomeHud.Show(Boarder, Banner("Welcome aboard, sailor!"), ?DisplayTime := 3.0)

            # Only open a boarding slot if the trigger still has room.
            if (BoardTrigger.GetTriggerCountRemaining() > 0):
                BoardTrigger.Trigger(Boarder)

Line by line:

  • @editable DockTrigger / BoardTrigger / WelcomeHud β€” you MUST declare placed devices as editable fields; a bare SomeTrigger.Trigger() would fail with Unknown identifier. After compiling, wire each field to a device in the UEFN Details panel.
  • Banner<localizes>(S:string):message β€” the HUD Show overload wants a message, not a raw string. This helper is the correct, supported way to build one. There is no StringToMessage.
  • DockTrigger.TriggeredEvent.Subscribe(OnDockStepped) β€” a listenable(?agent) event hands the handler an optional agent, so the method signature is (Agent : ?agent).
  • GetPlayspace().GetPlayers() β€” returns the raw array of every player. This is the array we filter.
  • The for: P : AllPlayers / Char := P.GetFortCharacter[] / Char.GetHealth() > 50.0 do: P block is the filter. Every line after the loop variable is a failable clause. GetFortCharacter[] fails (and skips the player) if they have no character; GetHealth() > 50.0 skips anyone at or below half health. Only players that pass both end up in Survivors.
  • The second for (Boarder : Survivors) iterates only the filtered survivors β€” no health checks needed, they already passed.
  • WelcomeHud.Show(Boarder, ..., ?DisplayTime := 3.0) β€” the targeted-agent overload shows the banner on just that player's screen for 3 seconds.
  • BoardTrigger.GetTriggerCountRemaining() > 0 gates the boarding: once the board trigger's max count is used up, we stop firing it, so only the first N survivors get aboard.

Common patterns

Pattern 1 β€” Filter creative objects by tag, then set up each one

Filter the array returned by a tag lookup so you only touch the pirate-ship decorations, then configure each matching trigger's reset delay.

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

cove_setup := class(creative_device):

    @editable MasterTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        # Give the master trigger 5 uses and a 2 second reset.
        MasterTrigger.SetMaxTriggerCount(5)
        MasterTrigger.SetResetDelay(2.0)

        # Read back what we set to confirm the boarding cap.
        Remaining := MasterTrigger.GetTriggerCountRemaining()
        Delay := MasterTrigger.GetResetDelay()

        # Only enable the trigger if we actually have slots configured.
        if (Remaining > 0 and Delay > 0.0):
            MasterTrigger.Enable()
        else:
            MasterTrigger.Disable()

Pattern 2 β€” Filter a payload array of agents before showing HUD

Collect agents into an array, filter out any that are false/unwrap-fail, and clear + re-show HUD for the valid ones.

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

lagoon_hud := class(creative_device):

    @editable AnnounceHud : hud_message_device = hud_message_device{}
    @editable StartTrigger : trigger_device = trigger_device{}

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

    OnBegin<override>()<suspends>:void =
        StartTrigger.TriggeredEvent.Subscribe(OnStart)

    OnStart(MaybeAgent : ?agent) : void =
        # Clear any old banners before the new wave.
        AnnounceHud.ClearAllMessages()

        Everyone := GetPlayspace().GetPlayers()

        # Filter: keep only the agents that are actually present players.
        Present := for (A : Everyone, _ := A.GetFortCharacter[]) { A }

        AnnounceHud.SetText(Note("The lagoon race begins!"))
        for (Racer : Present):
            AnnounceHud.Show(Racer)

Pattern 3 β€” Count the filtered subset and drive the trigger by size

Filter first, then use the length of the resulting array to decide whether to trigger.

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

clifftop_gate := class(creative_device):

    @editable CheckTrigger : trigger_device = trigger_device{}
    @editable GateTrigger : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        CheckTrigger.TriggeredEvent.Subscribe(OnCheck)

    OnCheck(MaybeAgent : ?agent) : void =
        AllPlayers := GetPlayspace().GetPlayers()

        # Filter: keep only full-shield players.
        Ready := for:
            P : AllPlayers
            Char := P.GetFortCharacter[]
            Char.GetShield() >= 100.0
        do:
            P

        # Open the gate only if at least 3 players are ready.
        if (Ready.Length >= 3):
            GateTrigger.Trigger()
        else:
            GateTrigger.Disable()

Gotchas

  • Filter clauses must be failable. for (P : Players, Char := P.GetFortCharacter[], ...) uses [] (square brackets) because GetFortCharacter[] is a <decides> call that can fail. If you write a comparison it must be a failable one like >, >=, =. A non-failable expression in the filter position is a compile error.
  • Filtering builds a NEW array β€” it never mutates the original. Survivors is separate from AllPlayers. Assign the result; don't expect the source array to shrink.
  • message, not string. hud_message_device.Show(Agent, Message, ...) and SetText take a message. Use a <localizes> helper (Banner("...")). There is no StringToMessage, and passing a bare "text" will not compile.
  • Unwrap the event's optional agent. TriggeredEvent is listenable(?agent). If you need the specific triggering player, unwrap with if (A := MaybeAgent?): before using it β€” it can be false when triggered from code.
  • GetTriggerCountRemaining() returns 0 when the max is unlimited. If you set SetMaxTriggerCount(0) (no limit), a Remaining > 0 guard will read 0 and skip β€” so only gate on remaining count when you have actually set a finite max.
  • No int/float auto-convert. GetHealth() and GetShield() return float; compare against 50.0, not 50. Ready.Length is an int; compare against 3, not 3.0.
  • Wire the fields. Editable device fields default to empty placeholders. If you forget to assign the real placed device in the Details panel, calls silently do nothing at runtime.
πŸ”’

Keep going β€” free

You've read the intro. The rest of this lesson is free for members. Sign in to continue and track your progress.

Sign in free to continue this lesson
Pass the quiz above to chart this quest in your Journal.

Sources

/guides/filter-an-array
Source

Biloxi Studios original lesson

Guided course

Add this lesson to your free study plan.

🧭 The Keeper’s log

Quest complete? Chart your next heading from the 🐻 North Jungle expedition.

β›΅ Take me there