Overview
The visual_effect_powerup_device is a placed UEFN device that applies a configurable glow or outline visual effect to any player who picks it up. It solves three common design problems at once:
- Visibility signalling — make a flag carrier, VIP, or "it" player visually distinct to everyone on the island.
- Timed buffs — the effect expires automatically after a duration you control from Verse with
SetDuration/GetDuration. - Scripted grants — call
Pickup(Agent)to force-apply the effect without the player physically walking over the pickup.
Reach for this device whenever you need a purely visual timed status effect. For damage multipliers or health restoration, use the sibling damage_amplifier_powerup_device or health_powerup_device instead.
API Reference
visual_effect_powerup_device
Used to trigger a visual effect (a glow or an outline) when
agents pick it up.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from powerup_device.
visual_effect_powerup_device<public> := class<concrete><final>(powerup_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
ItemPickedUpEvent |
ItemPickedUpEvent<public>:listenable(agent) |
Signaled when the powerup is picked up by an agent. Sends the agent that picked up the powerup. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Spawn |
Spawn<public>():void |
Spawns the powerup into the experience so users can interact with it. |
Despawn |
Despawn<public>():void |
Despawns this powerup from the experience. |
SetDuration |
SetDuration<public>(Time:float):void |
Updates the Duration for this powerup, clamped to the Min and Max defined in the device. Will not apply to any currently applied effects. |
GetDuration |
GetDuration<public>()<transacts>:float |
Returns the Duration that this powerup will be active for on any player it is applied to. |
GetRemainingTime |
GetRemainingTime<public>(Agent:agent)<transacts>:float |
If the Agent has the effect applied to them, this will return the remaining time the effect has. Returns -1.0 if the effect has an infinite duration. Returns 0.0 if the Agent does not have the effect applied. |
HasEffect |
HasEffect<public>(Agent:agent)<transacts><decides>:void |
Returns the Agent has the powerup's effect (or another of the same type) applied to them. |
IsSpawned |
IsSpawned<public>()<transacts><decides>:void |
Succeeds if the powerup is currently spawned. |
Pickup |
Pickup<public>(Agent:agent):void |
Grants this powerup to Agent. |
Pickup |
Pickup<public>():void |
Grants this powerup without an agent reference. Requires Apply To set to All Players. |
powerup_device
Base class for various powerup devices offering common events like
ItemPickedUpEvent.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
powerup_device<public> := class<abstract><epic_internal>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
ItemPickedUpEvent |
ItemPickedUpEvent<public>:listenable(agent) |
Signaled when the powerup is picked up by an agent. Sends the agent that picked up the powerup. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Spawn |
Spawn<public>():void |
Spawns the powerup into the experience so users can interact with it. |
Despawn |
Despawn<public>():void |
Despawns this powerup from the experience. |
SetDuration |
SetDuration<public>(Time:float):void |
Updates the Duration for this powerup, clamped to the Min and Max defined in the device. Will not apply to any currently applied effects. |
GetDuration |
GetDuration<public>()<transacts>:float |
Returns the Duration that this powerup will be active for on any player it is applied to. |
GetRemainingTime |
GetRemainingTime<public>(Agent:agent)<transacts>:float |
If the Agent has the effect applied to them, this will return the remaining time the effect has. Returns -1.0 if the effect has an infinite duration. Returns 0.0 if the Agent does not have the effect applied. |
HasEffect |
HasEffect<public>(Agent:agent)<transacts><decides>:void |
Returns the Agent has the powerup's effect (or another of the same type) applied to them. |
IsSpawned |
IsSpawned<public>()<transacts><decides>:void |
Succeeds if the powerup is currently spawned. |
Pickup |
Pickup<public>(Agent:agent):void |
Grants this powerup to Agent. |
Pickup |
Pickup<public>():void |
Grants this powerup without an agent reference. Requires Apply To set to All Players. |
Walkthrough
Scenario: The Glowing Flag Carrier
A capture-the-flag variant: when a player steps on a trigger plate at the flag stand, the Visual Effect Powerup is granted to them so every opponent can see the carrier glowing. A second trigger (the end-zone plate) despawns the powerup and resets the round.
Place in your UEFN level:
- One
visual_effect_powerup_device(set Auto Spawn to Off in its properties so Verse controls spawning) - One
trigger_devicenamedFlagPickupTrigger(the flag stand) - One
trigger_devicenamedEndZoneTrigger(the scoring zone)
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Attach this Verse device to your level.
# Wire FlagPickupTrigger and EndZoneTrigger in the Details panel.
flag_carrier_device := class(creative_device):
# The visual-effect powerup that makes the carrier glow.
@editable
GlowPowerup : visual_effect_powerup_device = visual_effect_powerup_device{}
# Trigger at the flag stand — stepping here starts the carry.
@editable
FlagPickupTrigger : trigger_device = trigger_device{}
# Trigger at the scoring end-zone — stepping here ends the carry.
@editable
EndZoneTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# Set the glow duration to 60 seconds (clamped to device min/max).
GlowPowerup.SetDuration(60.0)
# Spawn the powerup so it is live in the world.
GlowPowerup.Spawn()
# Subscribe to the flag-stand trigger.
FlagPickupTrigger.TriggeredEvent.Subscribe(OnFlagPickup)
# Subscribe to the end-zone trigger.
EndZoneTrigger.TriggeredEvent.Subscribe(OnEndZoneReached)
# Also react whenever someone actually picks up the glow item.
GlowPowerup.ItemPickedUpEvent.Subscribe(OnGlowPickedUp)
# Called when a player steps on the flag-stand plate.
OnFlagPickup(Agent : ?agent) : void =
if (A := Agent?):
# Force-grant the glow effect to the triggering player.
GlowPowerup.Pickup(A)
# Called when a player steps on the end-zone plate.
OnEndZoneReached(Agent : ?agent) : void =
if (A := Agent?):
# Only reset if this agent actually has the effect.
if (GlowPowerup.HasEffect[A]):
# Despawn the pickup so no one else can grab it mid-reset.
GlowPowerup.Despawn()
# Re-spawn fresh for the next round.
GlowPowerup.Spawn()
# Called by ItemPickedUpEvent — Agent is a plain `agent` here (not optional).
OnGlowPickedUp(Agent : agent) : void =
# Log remaining time to confirm the effect is live.
# GetRemainingTime returns -1.0 for infinite, 0.0 if not applied.
_Remaining := GlowPowerup.GetRemainingTime(Agent)
Line-by-line explanation
| Line | What it does |
|---|---|
@editable GlowPowerup |
Exposes the device reference so you can wire it in the UEFN Details panel. |
SetDuration(60.0) |
Overrides the designer-set duration to exactly 60 s before OnBegin spawns the item. |
GlowPowerup.Spawn() |
Makes the pickup visible and interactable in the world. |
FlagPickupTrigger.TriggeredEvent.Subscribe(OnFlagPickup) |
Wires the trigger's event to our handler. |
GlowPowerup.Pickup(A) |
Force-grants the glow to the specific agent — no physical walk-over needed. |
GlowPowerup.HasEffect[A] |
<decides> method — must be called inside an if or if guard. Succeeds only if the effect is currently on that agent. |
GlowPowerup.Despawn() then Spawn() |
Resets the pickup for the next round. |
ItemPickedUpEvent.Subscribe(OnGlowPickedUp) |
The event sends a plain agent (not ?agent), so no unwrap is needed in this handler. |
GetRemainingTime(Agent) |
Returns seconds left; useful for UI or debug logging. |
Common patterns
Pattern 1 — Query the effect before granting it (avoid double-applying)
Before handing out the glow, check HasEffect so you never stack the effect on a player who already has it, and use GetRemainingTime to display how long they have left.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
glow_query_device := class(creative_device):
@editable
GlowPowerup : visual_effect_powerup_device = visual_effect_powerup_device{}
@editable
GrantTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
GlowPowerup.SetDuration(30.0)
GlowPowerup.Spawn()
GrantTrigger.TriggeredEvent.Subscribe(OnGrantRequested)
OnGrantRequested(Agent : ?agent) : void =
if (A := Agent?):
# Only grant if the player does NOT already have the effect.
if (not GlowPowerup.HasEffect[A]):
GlowPowerup.Pickup(A)
else:
# They already glow — check how many seconds remain.
Remaining := GlowPowerup.GetRemainingTime(A)
# Remaining > 0.0 means timed; -1.0 means infinite.
if (Remaining > 0.0):
# Could drive a UI countdown here.
dummy := Remaining # suppress unused-variable warning
Pattern 2 — Dynamic duration scaling and IsSpawned guard
Scale the glow duration based on a round number, and only spawn if the powerup is not already in the world.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
glow_round_scaler_device := class(creative_device):
@editable
GlowPowerup : visual_effect_powerup_device = visual_effect_powerup_device{}
# Round counter driven externally (e.g. incremented by a score manager).
var CurrentRound : int = 1
OnBegin<override>()<suspends> : void =
SpawnForRound()
# Call this whenever a new round starts.
SpawnForRound() : void =
# Each round adds 10 s to the glow, starting at 15 s.
NewDuration : float = 15.0 + (10.0 * IntToFloat(CurrentRound - 1))
GlowPowerup.SetDuration(NewDuration)
# Only spawn if not already present in the world.
if (not GlowPowerup.IsSpawned[]):
GlowPowerup.Spawn()
# Helper: Verse does not auto-convert int to float.
IntToFloat(N : int) : float =
# Multiply by 1.0 to coerce — standard Verse idiom.
return N * 1.0
Pattern 3 — Broadcast glow to ALL players (no-agent Pickup)
When a round starts, apply the glow to every player at once using the no-argument Pickup() overload. This requires the device's Apply To property set to All Players in the UEFN Details panel.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
glow_all_players_device := class(creative_device):
@editable
GlowPowerup : visual_effect_powerup_device = visual_effect_powerup_device{}
# A trigger that a game-manager device fires to start the "everyone glows" phase.
@editable
RoundStartTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
GlowPowerup.SetDuration(20.0)
GlowPowerup.Spawn()
RoundStartTrigger.TriggeredEvent.Subscribe(OnRoundStart)
GlowPowerup.ItemPickedUpEvent.Subscribe(OnAnyPickup)
# Fires when the round-start trigger is activated.
OnRoundStart(Agent : ?agent) : void =
# Apply To must be "All Players" in device settings for this overload.
GlowPowerup.Pickup()
# Fires once per player who receives the effect.
OnAnyPickup(Agent : agent) : void =
# Confirm the effect is on this agent and read the configured duration.
if (GlowPowerup.HasEffect[Agent]):
_Duration := GlowPowerup.GetDuration()
Gotchas
1. HasEffect and IsSpawned are <decides> — always call them inside if
Both methods use the <decides> effect, meaning they either succeed or fail rather than returning a bool. You must call them as conditions inside an if expression:
# CORRECT
if (GlowPowerup.HasEffect[Agent]):
...
# WRONG — compile error
Result := GlowPowerup.HasEffect(Agent)
2. ItemPickedUpEvent sends agent, but TriggeredEvent sends ?agent
ItemPickedUpEvent is typed listenable(agent) — the handler receives a plain agent, no unwrap needed. By contrast, trigger_device.TriggeredEvent is listenable(?agent) and requires if (A := Agent?): before use. Mixing these up is a common compile error.
3. SetDuration does NOT affect already-active effects
Calling SetDuration only changes the duration for future pickups. If a player already has the glow, their remaining time is unaffected. Despawn and re-spawn the device if you need to reset an active effect.
4. Pickup() (no-agent) requires Apply To = All Players in device settings
If you call the zero-argument Pickup() overload without setting Apply To to All Players in the UEFN Details panel, the call silently does nothing at runtime. Always verify this property when using the broadcast overload.
5. GetRemainingTime return values have special meaning
- Returns
0.0→ the agent does not have the effect. - Returns
-1.0→ the effect is active with infinite duration. - Returns
> 0.0→ seconds remaining on a timed effect.
Do not treat 0.0 as "just expired" — it means the effect was never applied (or has already ended).
6. Verse does not auto-convert int to float
SetDuration and GetDuration both use float. If you compute a duration from an int variable, multiply by 1.0 or use a helper function — the compiler will reject a bare int argument.