Sum an Array: Total Boost Score
In this lesson you'll learn to
- βAccumulate over an array to compute totals like collected boosts.
Accumulate over an array to compute totals like collected boosts.
π Reference & full walkthrough: Sum an Array: Total Boost Score
π§© Your capstone piece: Total-boosts and total-time aggregation
Overview
An array in Verse is a fixed-order container of same-typed values: []int, []float, []agent, etc. Summing an array is the gateway skill for almost every score system, leaderboard, damage calculator, or resource counter you will ever build in UEFN.
The pattern is always the same:
- Declare a
var Total : int = 0(orfloat). for (Value : MyArray)β iterate every element.set Total += Valueβ accumulate.- Use
Totalhowever you like: display it, compare it, award XP with it.
In this article the "however you like" part is a hud_message_device that flashes the gold total on every player's screen, triggered by the last pressure plate on a cel-shaded pirate ship docked in a sunny lagoon.
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. |
team
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).
team<native><public> := class<unique><epic_internal>:
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
Five pressure plates are hidden under treasure chests along the ship's deck. Stepping on each plate adds that chest's gold value to a running tally. The fifth plate fires a trigger_device that calls our Verse device, which sums the array and shows the grand total via hud_message_device.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
# Localisation helper β message params must be `message`, not raw string.
TreasureMessage<localizes>(S : string) : message = "{S}"
treasure_tally_device := class(creative_device):
# ββ Editable device references ββββββββββββββββββββββββββββββββββββββββββββ
# Wire this to the trigger_device that fires when the last chest is opened.
@editable
FinalChestTrigger : trigger_device = trigger_device{}
# HUD message device set to "All Players" in its properties.
@editable
ScoreHUD : hud_message_device = hud_message_device{}
# ββ Gold values for each of the five treasure chests βββββββββββββββββββββ
# Edit these in the Details panel or hard-code them here.
# Index 0 = bow chest, 1 = port side, 2 = starboard, 3 = crow's nest, 4 = captain's cabin.
@editable
ChestGoldValues : []int = array{50, 120, 75, 200, 350}
# ββ Lifecycle βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
OnBegin<override>()<suspends> : void =
# Subscribe: when the final chest trigger fires, run OnFinalChestTriggered.
FinalChestTrigger.TriggeredEvent.Subscribe(OnFinalChestTriggered)
# Give the HUD message device a persistent display time so the
# score stays on screen until we explicitly hide it.
ScoreHUD.SetDisplayTime(0.0)
# ββ Event handler βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# TriggeredEvent sends ?agent, so the handler receives ?agent.
OnFinalChestTriggered(MaybeAgent : ?agent) : void =
# 1. Sum the chest gold values.
var TotalGold : int = 0
for (GoldValue : ChestGoldValues):
set TotalGold += GoldValue
# 2. Build the display string and push it to the HUD.
# Show() with no agent arg broadcasts to ALL players.
ScoreHUD.Show(TreasureMessage("Treasure Haul: {TotalGold} Gold!"))
# 3. If a real agent triggered the plate, also show them a personal
# confirmation using the agent-specific overload of Show.
if (A := MaybeAgent?):
ScoreHUD.Show(A, TreasureMessage("You found it all! {TotalGold} Gold!"))
Line-by-line explanation
| Lines | What's happening |
|---|---|
TreasureMessage<localizes> |
Verse's message type requires a <localizes> function β you cannot pass a raw string to SetText or Show. |
@editable FinalChestTrigger |
Declares the trigger_device as an editable field so you can wire it in the UEFN Details panel. |
@editable ChestGoldValues : []int |
An editable int array β you can tweak chest values in the editor without touching code. |
FinalChestTrigger.TriggeredEvent.Subscribe(...) |
Hooks our handler to the trigger's event. The event fires with ?agent (optional agent). |
ScoreHUD.SetDisplayTime(0.0) |
0.0 means the message stays on screen indefinitely β great for end-of-round totals. |
for (GoldValue : ChestGoldValues) |
Iterates every element in the array. No index needed for a simple sum. |
set TotalGold += GoldValue |
Accumulates the running total. set is required when mutating a var. |
ScoreHUD.Show(TreasureMessage(...)) |
Broadcasts the total to all players. |
if (A := MaybeAgent?) |
Safely unwraps the optional agent before calling the agent-specific Show overload. |
Common patterns
Pattern 1 β Summing floats (damage dealt across a round)
The same loop works for []float. Here a trigger fires at round end and the device sums each player's damage log.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
DamageMessage<localizes>(S : string) : message = "{S}"
damage_summary_device := class(creative_device):
@editable
RoundEndTrigger : trigger_device = trigger_device{}
@editable
DamageHUD : hud_message_device = hud_message_device{}
# Damage dealt by each player this round (populated elsewhere in your project).
@editable
DamageLog : []float = array{340.5, 210.0, 512.75, 88.25}
OnBegin<override>()<suspends> : void =
RoundEndTrigger.TriggeredEvent.Subscribe(OnRoundEnd)
DamageHUD.SetDisplayTime(5.0) # Show for 5 seconds then auto-hide.
OnRoundEnd(MaybeAgent : ?agent) : void =
var TotalDamage : float = 0.0
for (D : DamageLog):
set TotalDamage += D
# Truncate to int for a cleaner display.
TotalInt : int = Int[TotalDamage] # failable cast β use in if
if (T := Int[TotalDamage]):
DamageHUD.Show(DamageMessage("Team Damage: {T}"))
else:
DamageHUD.Show(DamageMessage("Team Damage: (overflow)"))
Pattern 2 β Conditional sum (only count chests the player actually opened)
Use an if inside the for loop to filter which elements contribute to the total. Here only chests worth more than 100 gold count as "legendary" and are summed separately. The trigger is also reconfigured at runtime with SetMaxTriggerCount.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
LegendaryMsg<localizes>(S : string) : message = "{S}"
legendary_tally_device := class(creative_device):
@editable
BonusTrigger : trigger_device = trigger_device{}
@editable
BonusHUD : hud_message_device = hud_message_device{}
@editable
AllChestValues : []int = array{50, 120, 75, 200, 350, 30, 500}
OnBegin<override>()<suspends> : void =
# Allow this bonus trigger to fire only once per match.
BonusTrigger.SetMaxTriggerCount(1)
BonusTrigger.TriggeredEvent.Subscribe(OnBonusTriggered)
OnBonusTriggered(MaybeAgent : ?agent) : void =
# Sum ONLY legendary chests (value > 100).
var LegendaryTotal : int = 0
var LegendaryCount : int = 0
for (Value : AllChestValues, Value > 100):
set LegendaryTotal += Value
set LegendaryCount += 1
BonusHUD.Show(LegendaryMsg("Legendary Chests: {LegendaryCount} | Gold: {LegendaryTotal}"))
# Disable the trigger so it can never fire again (belt-and-suspenders).
BonusTrigger.Disable()
Pattern 3 β Displaying a live running total as each chest is found
Each chest has its own trigger_device. Every trigger fires OnChestFound, which appends the chest's value to a mutable array and immediately updates the HUD. This uses GetTriggerCountRemaining to know how many chests are left.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
RunningMsg<localizes>(S : string) : message = "{S}"
running_tally_device := class(creative_device):
# One trigger per chest β wire all five in the Details panel.
@editable
Chest1Trigger : trigger_device = trigger_device{}
@editable
Chest2Trigger : trigger_device = trigger_device{}
@editable
Chest3Trigger : trigger_device = trigger_device{}
@editable
LiveHUD : hud_message_device = hud_message_device{}
# Gold value for each chest, parallel to the triggers above.
@editable
GoldValues : []int = array{50, 120, 350}
# Accumulate found gold at runtime.
var CollectedGold : []int = array{}
OnBegin<override>()<suspends> : void =
LiveHUD.SetDisplayTime(0.0) # Persistent display.
Chest1Trigger.TriggeredEvent.Subscribe(OnChest1Found)
Chest2Trigger.TriggeredEvent.Subscribe(OnChest2Found)
Chest3Trigger.TriggeredEvent.Subscribe(OnChest3Found)
# Helper: append a value, recompute sum, refresh HUD.
AddAndRefresh(GoldIndex : int) : void =
if (Value := GoldValues[GoldIndex]):
set CollectedGold = CollectedGold + array{Value}
var Total : int = 0
for (G : CollectedGold):
set Total += G
Remaining : int = Chest1Trigger.GetTriggerCountRemaining()
LiveHUD.Show(RunningMsg("Gold so far: {Total}"))
OnChest1Found(MaybeAgent : ?agent) : void = AddAndRefresh(0)
OnChest2Found(MaybeAgent : ?agent) : void = AddAndRefresh(1)
OnChest3Found(MaybeAgent : ?agent) : void = AddAndRefresh(2)
Gotchas
1. message is NOT a string
hud_message_device.Show() and SetText() both require a message, not a plain string. Always declare a <localizes> helper:
MyMsg<localizes>(S : string) : message = "{S}"
There is no StringToMessage function β the <localizes> function is the only bridge.
2. int and float do not auto-convert
If your chest values are []float but you want to display a rounded integer, use the failable Int[] cast inside an if:
if (T := Int[TotalFloat]):
HUD.Show(MyMsg("{T}"))
Do not write TotalFloat + 0 hoping it becomes an int β the compiler will reject it.
3. TriggeredEvent sends ?agent, not agent
The handler signature must be (MaybeAgent : ?agent). Forgetting the ? causes a type mismatch compile error. Always unwrap before using:
if (A := MaybeAgent?):
HUD.Show(A, MyMsg("Personal message"))
4. @editable arrays are set at edit time, not runtime
You cannot array.Add() to an @editable array β arrays in Verse are immutable by default. Use a separate var field (e.g. var CollectedGold : []int = array{}) and reassign with concatenation (set CollectedGold = CollectedGold + array{NewValue}).
5. SetMaxTriggerCount clamps to [0, 20]
Passing a value outside that range silently clamps it. 0 means unlimited β not zero triggers. If you want a one-shot trigger, pass 1.
6. Empty array sum is zero β that's fine
A for loop over an empty array simply never executes, leaving Total at its initial value. This is safe and expected behaviour, not a bug.
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/sum-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