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 readGetTriggerCountRemaining()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 bareSomeTrigger.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 HUDShowoverload wants amessage, not a raw string. This helper is the correct, supported way to build one. There is noStringToMessage.DockTrigger.TriggeredEvent.Subscribe(OnDockStepped)β alistenable(?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: Pblock 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.0skips anyone at or below half health. Only players that pass both end up inSurvivors. - 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() > 0gates 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) becauseGetFortCharacter[]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.
Survivorsis separate fromAllPlayers. Assign the result; don't expect the source array to shrink. message, notstring.hud_message_device.Show(Agent, Message, ...)andSetTexttake amessage. Use a<localizes>helper (Banner("...")). There is noStringToMessage, and passing a bare"text"will not compile.- Unwrap the event's optional agent.
TriggeredEventislistenable(?agent). If you need the specific triggering player, unwrap withif (A := MaybeAgent?):before using it β it can befalsewhen triggered from code. GetTriggerCountRemaining()returns0when the max is unlimited. If you setSetMaxTriggerCount(0)(no limit), aRemaining > 0guard will read0and skip β so only gate on remaining count when you have actually set a finite max.- No int/float auto-convert.
GetHealth()andGetShield()returnfloat; compare against50.0, not50.Ready.Lengthis anint; compare against3, not3.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 lessonSources
/guides/filter-an-arrayBiloxi Studios original lesson
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