Overview
The earth_sprite_device is Fortnite's friendly loot-trader. A player walks up, hands it a weapon, and after a short grant timer the Sprite returns a random legendary weapon or an item from a custom list you configured in the device's Details panel.
Reach for it when you want a risk/reward economy beat: a vault room where players gamble their starter pistol for a chance at something better, a boss-arena reward you only unlock mid-match, or a one-trade-per-player merchant.
The Verse API gives you four powerful levers over the placed device:
- Gate granting with
EnableItemGranting()/DisableItemGranting()— the Sprite can still consume a weapon while granting is off (useful for a "closed shop" phase). - Gate per-player trading with
EnableTradingForPlayer(Agent)/DisableTradingForPlayer(Agent)— enabling a player also resets their trade count. - Hide/Show the Sprite to reveal it as a reward.
- React to
WeaponConsumedEvent(a weapon was fed) andGrantTimerCompletedEvent(the loot is about to drop).
Because it's a placed device, you must expose it as an @editable field on your own creative_device class before you can call any of these.
API Reference
earth_sprite_device
Use to create a sprite that players can trade in a weapon for a random legendary weapon or a custom item list.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
earth_sprite_device<public> := class<concrete><final>(creative_device_base, enableable):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
WeaponConsumedEvent |
WeaponConsumedEvent<public>:listenable(agent) |
Triggers when a player gives the Earth Sprite a weapon. Sends the triggering agent. |
GrantTimerCompletedEvent |
GrantTimerCompletedEvent<public>:listenable(?agent) |
Triggers when the grant timer has completed. Sends the triggering agent. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
EnableItemGranting |
EnableItemGranting<public>():void |
Enable the device's ability to grant items. |
DisableItemGranting |
DisableItemGranting<public>():void |
Disable the device's ability to grant items. Can still interact and consume weapons. |
Hide |
Hide<public>():void |
Makes the Earth Sprite invisible. |
Show |
Show<public>():void |
Makes the Earth Sprite visible. |
EnableTradingForPlayer |
EnableTradingForPlayer<public>(Agent:agent):void |
Allows a agent to trade, and will reset the agent's trade count for this Sprite. |
DisableTradingForPlayer |
DisableTradingForPlayer<public>(Agent:agent):void |
Prevents the agent from trading. |
Walkthrough
Let's build a gated merchant shrine. The Sprite starts hidden and unable to grant. When a player steps on a trigger plate, we Show the Sprite, enable granting, and allow that one player to trade. Each time a weapon is consumed we count it, and when the grant timer completes we lock that player out again — one trade per visit.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
merchant_shrine := class(creative_device):
@editable
Sprite : earth_sprite_device = earth_sprite_device{}
@editable
OpenPlate : trigger_device = trigger_device{}
# Tracks how many weapons the current visitor has fed the Sprite.
var TradesThisVisit : int = 0
OnBegin<override>()<suspends> : void =
# Start with the shrine dormant.
Sprite.Hide()
Sprite.DisableItemGranting()
# React to player activity on the Sprite.
Sprite.WeaponConsumedEvent.Subscribe(OnWeaponConsumed)
Sprite.GrantTimerCompletedEvent.Subscribe(OnGrantComplete)
# The plate opens the shrine for whoever steps on it.
OpenPlate.TriggeredEvent.Subscribe(OnPlateStepped)
# trigger_device hands us an ?agent — unwrap it before use.
OnPlateStepped(Agent : ?agent) : void =
if (Player := Agent?):
set TradesThisVisit = 0
Sprite.Show()
Sprite.EnableItemGranting()
Sprite.EnableTradingForPlayer(Player) # also resets their trade count
# WeaponConsumedEvent sends a plain agent (not optional).
OnWeaponConsumed(Player : agent) : void =
set TradesThisVisit = TradesThisVisit + 1
# GrantTimerCompletedEvent sends an ?agent.
OnGrantComplete(Agent : ?agent) : void =
if (Player := Agent?):
# Loot has dropped — close the shrine to this player.
Sprite.DisableTradingForPlayer(Player)
Sprite.DisableItemGranting()
Sprite.Hide()
Line by line:
- The
@editablefieldsSpriteandOpenPlatelet you drag your placed Earth Sprite and trigger into these slots in the Details panel. Without the@editablefield, callingSprite.Hide()fails with Unknown identifier. var TradesThisVisit : int = 0is class-level mutable state we can read across event handlers.- In
OnBeginwe put the shrine in its dormant state (Hide+DisableItemGranting) and subscribe three handlers. Subscriptions live inOnBegin; the handlers themselves are methods at class scope. OnPlateSteppedreceives?agentbecausetrigger_device.TriggeredEventis alistenable(?agent). We unwrap withif (Player := Agent?):. We reset our counter,Showthe Sprite, turn granting on, and callEnableTradingForPlayer— which conveniently resets that player's internal trade count too.OnWeaponConsumedfires the instant a weapon is fed; its event hands a non-optionalagent, so no unwrap is needed. We bump our counter.OnGrantCompletefires when the reward is handed out. We disable trading for that player, turn granting off, and hide the Sprite — enforcing one trade per visit.
Common patterns
One-time treasure reveal
Keep the Sprite hidden until a quest objective is done, then reveal it as a usable reward. Here a trigger acts as the "objective complete" signal.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
treasure_reveal := class(creative_device):
@editable
Sprite : earth_sprite_device = earth_sprite_device{}
@editable
ObjectiveDone : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
Sprite.Hide()
Sprite.DisableItemGranting()
ObjectiveDone.TriggeredEvent.Subscribe(OnObjectiveDone)
OnObjectiveDone(Agent : ?agent) : void =
# Reveal and switch the Sprite on for everyone.
Sprite.Show()
Sprite.EnableItemGranting()
Per-player single trade with WeaponConsumedEvent
Lock a player out the moment they feed the Sprite a weapon — no waiting for the grant timer.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
once_per_player := class(creative_device):
@editable
Sprite : earth_sprite_device = earth_sprite_device{}
OnBegin<override>()<suspends> : void =
Sprite.EnableItemGranting()
Sprite.WeaponConsumedEvent.Subscribe(OnTraded)
OnTraded(Player : agent) : void =
# As soon as they trade, prevent any further trades from this player.
Sprite.DisableTradingForPlayer(Player)
Closed-shop phase using GrantTimerCompletedEvent
Let the Sprite consume weapons during a build phase but only release loot at the start of the next round.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
shop_phases := class(creative_device):
@editable
Sprite : earth_sprite_device = earth_sprite_device{}
@editable
RoundStart : button_device = button_device{}
OnBegin<override>()<suspends> : void =
# Shop accepts weapons but withholds loot for now.
Sprite.DisableItemGranting()
RoundStart.InteractedWithEvent.Subscribe(OnRoundStart)
Sprite.GrantTimerCompletedEvent.Subscribe(OnGranted)
OnRoundStart(Agent : agent) : void =
# Open the floodgates.
Sprite.EnableItemGranting()
OnGranted(Agent : ?agent) : void =
if (Player := Agent?):
# After one grant this round, pause granting again.
Sprite.DisableItemGranting()
Gotchas
@editablefield is mandatory. You cannot callearth_sprite_device.Hide()on a bare type — you must declare a placed instance as an@editablefield and assign the real device in the Details panel.- Two different event signatures.
WeaponConsumedEventislistenable(agent)— the handler gets a plainagent.GrantTimerCompletedEventislistenable(?agent)— the handler gets an?agentyou must unwrap withif (Player := Agent?):. Mixing them up is a compile error. - Granting off ≠ interaction off.
DisableItemGranting()still lets players walk up and feed weapons (andWeaponConsumedEventstill fires) — it only stops the reward. To stop a specific player entirely, useDisableTradingForPlayer. EnableTradingForPlayerresets the trade count. If you re-enable a player to give them another go, remember their per-Sprite trade count is wiped — design your one-trade limits around that.- Hide doesn't disable logic.
Hide()only changes visibility; the device still functions. Pair it withDisableItemGranting()if you want the shrine truly dormant. - Subscribe in OnBegin. Event handlers are class methods; you wire them up once inside
OnBegin<override>()<suspends>. Subscribing inside a handler can double-fire.