Overview
The hero_chest_device represents an indestructible chest placed on your island. Out of the box it sits there looking pretty, but from Verse you can:
- Lock and unlock it globally (
LockForAll/UnlockForAll) or per-player (Lock/Unlock). - Force it open programmatically (
Open) — perfect for cinematic reveals or puzzle rewards. - React when a player opens it via
OpenEvent— great for tracking loot pickups, awarding bonus points, or triggering the next phase of your game. - Query its state at any time (
IsOpen,IsLocked,IsLockedForAll) to branch your game logic. - Read its rank (
GetRankAsString) to display flavour text or gate further logic.
Reach for hero_chest_device whenever you need a loot container whose availability is driven by game state rather than static placement settings.
API Reference
hero_chest_device
An indestructible chest that can be locked and unlocked.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
hero_chest_device<public> := class<concrete><final>(creative_device_base, enableable):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
OpenEvent |
OpenEvent<public>:listenable(?agent) |
Triggers whenever the chest is opened, returning the agent who opened it if applicable. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Open |
Open<public>():void |
Open the chest. |
IsOpen |
IsOpen<public>()<transacts><decides>:void |
Succeeds if the chest is currently open, fails if it's closed. |
LockForAll |
LockForAll<public>():void |
Lock the chest for everyone, and set this chest's default state to Locked. |
UnlockForAll |
UnlockForAll<public>():void |
Unlock the chest for everyone, and set this chest's default state to Unlocked. |
IsLockedForAll |
IsLockedForAll<public>()<transacts><decides>:void |
Succeeds if the chest's default locked state is Locked. * The default locked state is initialized by the Start Locked user option and is overridden by LockForAll and UnlockForAll. |
Lock |
Lock<public>(Agent:agent):void |
Lock the chest for Agent. Has no effect if the chest is open. |
Unlock |
Unlock<public>(Agent:agent):void |
Unlock the chest for Agent. Has no effect if the chest is open. |
IsLocked |
IsLocked<public>(Agent:agent)<transacts><decides>:void |
Succeeds if the chest is locked for Agent. |
GetRankAsString |
GetRankAsString<public>():string |
Returns the chest rank as a string. |
Walkthrough
Scenario: A puzzle room with a pressure plate. When a player steps on the plate the vault chest unlocks for that player only, plays a short delay, then pops open for everyone. A UI message announces the chest's rank. Any subsequent opener triggers a bonus-score event.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Localized helper — message params require a <localizes> wrapper
RankMessage<localizes>(S : string) : message = "Chest Rank: {S}"
OpenedMessage<localizes>(S : string) : message = "A player just looted the {S} chest!"
vault_puzzle_device := class(creative_device):
# The pressure plate players step on to earn access
@editable
Plate : trigger_device = trigger_device{}
# The hero chest sitting behind the vault door
@editable
Chest : hero_chest_device = hero_chest_device{}
# HUD message device to announce the rank
@editable
HUD : hud_message_device = hud_message_device{}
OnBegin<override>()<suspends> : void =
# Chest starts locked for everyone (set "Start Locked" = true in device options)
# Subscribe to the plate so we know who solved the puzzle
Plate.TriggeredEvent.Subscribe(OnPlateTriggered)
# Subscribe to the chest so we can react whenever it is opened
Chest.OpenEvent.Subscribe(OnChestOpened)
# Called when any player steps on the pressure plate
OnPlateTriggered(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Unlock the chest only for the player who solved the puzzle
Chest.Unlock(A)
# Kick off the timed reveal as a concurrent task
spawn { TimedReveal() }
# After a short dramatic pause, open the chest for everyone
TimedReveal()<suspends> : void =
Sleep(2.0)
# Announce the rank before popping it open
RankStr := Chest.GetRankAsString()
HUD.SetText(RankMessage(RankStr))
# Open fires the OpenEvent, so OnChestOpened will also run
Chest.Open()
# Fires every time the chest is opened (including our forced Open above)
OnChestOpened(MaybeAgent : ?agent) : void =
RankStr := Chest.GetRankAsString()
# Re-lock for everyone after it has been opened once
Chest.LockForAll()
Line-by-line explanation
| Lines | What's happening |
|---|---|
RankMessage<localizes> |
Verse message params must come from a <localizes> function — you cannot pass a raw string. |
@editable fields |
Every device reference must be an @editable field; bare identifiers fail to compile. |
Plate.TriggeredEvent.Subscribe(OnPlateTriggered) |
Hooks the plate's event to our handler at game start. |
Chest.OpenEvent.Subscribe(OnChestOpened) |
Hooks the chest's open event — fires whether a player or our code opens it. |
if (A := MaybeAgent?) |
TriggeredEvent delivers ?agent; we must unwrap it before calling Chest.Unlock(A). |
Chest.Unlock(A) |
Unlocks only for the triggering player — everyone else still sees it locked. |
spawn { TimedReveal() } |
Runs the suspending coroutine concurrently so the handler returns immediately. |
Chest.GetRankAsString() |
Returns the rank (e.g. "S") as a plain string we can embed in a localized message. |
Chest.Open() |
Forces the chest open regardless of lock state — also fires OpenEvent. |
Chest.LockForAll() |
Re-locks globally after the reveal so it can't be looted again. |
Common patterns
Pattern 1 — Global timed loot drop (UnlockForAll + IsLockedForAll)
Unlock the chest for everyone at the 60-second mark, then re-lock it 30 seconds later if nobody opened it.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
timed_loot_drop_device := class(creative_device):
@editable
Chest : hero_chest_device = hero_chest_device{}
OnBegin<override>()<suspends> : void =
# Wait 60 seconds into the match
Sleep(60.0)
Chest.UnlockForAll()
# Give players 30 seconds to grab it
Sleep(30.0)
# Only re-lock if nobody opened it yet
if (Chest.IsOpen[]):
# Chest is already open — nothing to do
else:
# Chest is still closed; re-lock so latecomers can't grab it
if (not Chest.IsLockedForAll[]):
Chest.LockForAll()
Note:
IsOpenandIsLockedForAllare<decides>functions — call them inside anifexpression. They do not returnbool.
Pattern 2 — Per-player VIP gate (Lock / Unlock / IsLocked)
Only players on a VIP list (signalled by a separate button device) can open the chest. Everyone else finds it locked.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
vip_chest_device := class(creative_device):
@editable
Chest : hero_chest_device = hero_chest_device{}
# A button only VIPs can reach (placed behind a barrier, etc.)
@editable
VIPButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
# Start locked for everyone (also set Start Locked = true in device options)
Chest.LockForAll()
VIPButton.InteractedWithEvent.Subscribe(OnVIPButtonPressed)
OnVIPButtonPressed(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# Check whether this agent is still locked before unlocking
if (Chest.IsLocked[A]):
Chest.Unlock(A)
Pattern 3 — React to an open event and display rank (OpenEvent + GetRankAsString)
Every time the chest is opened, broadcast the rank to a HUD message so spectators can see what tier of loot dropped.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Native }
RankBroadcast<localizes>(R : string) : message = "Loot Rank {R} chest opened!"
rank_announcer_device := class(creative_device):
@editable
Chest : hero_chest_device = hero_chest_device{}
@editable
HUD : hud_message_device = hud_message_device{}
OnBegin<override>()<suspends> : void =
Chest.OpenEvent.Subscribe(OnChestOpened)
OnChestOpened(MaybeAgent : ?agent) : void =
Rank := Chest.GetRankAsString()
HUD.SetText(RankBroadcast(Rank))
# Optionally show the message to the specific opener
if (A := MaybeAgent?):
HUD.Show(A)
Gotchas
1. IsOpen, IsLocked, IsLockedForAll are <decides> — use them in if
These methods do not return a bool. They succeed or fail. Always call them as the condition of an if:
# CORRECT
if (Chest.IsOpen[]):
...
# WRONG — does not compile
Result := Chest.IsOpen() # IsOpen has no return value and requires a decision context
2. Lock(Agent) and Unlock(Agent) have no effect on an already-open chest
If Chest.Open() has already been called (or a player opened it), calling Lock(Agent) silently does nothing. Check IsOpen[] first if you need to guard against this.
3. OpenEvent fires for both player opens and programmatic Open() calls
Don't assume MaybeAgent? will always succeed — when your code calls Chest.Open() directly, the agent payload is false (no agent). Always unwrap with if (A := MaybeAgent?).
4. message params require <localizes> — no raw strings
hud_message_device.SetText takes a message, not a string. You cannot pass GetRankAsString() directly. Wrap it:
RankMsg<localizes>(S : string) : message = "Rank: {S}"
HUD.SetText(RankMsg(Chest.GetRankAsString()))
5. LockForAll sets the default state — it persists across resets
Calling LockForAll() changes the chest's default locked state, meaning a subsequent Reset() will restore it to locked. If you want a chest that resets to unlocked, call UnlockForAll() before or after resetting.
6. Every device reference must be an @editable field
You cannot write hero_chest_device{}.Open() inline. Declare the chest as an @editable field in your class(creative_device) and wire it up in the UEFN Details panel.