Reference Devices compiles

campfire_device: Healing Zones That React to Players

The `campfire_device` places a healing campfire in your UEFN island that periodically pulses health to nearby players. With Verse you can light or extinguish it programmatically, feed it wood to keep it burning longer, and react to every player who wanders into — or out of — its warm glow. Whether you're building a survival game where fire is a precious resource or a checkpoint system that rewards players who reach a safe zone, the campfire device is your tool.

Updated Examples verified on the live UEFN compiler
Watch the Knotcampfire_device in ~90 seconds.

Overview

The campfire_device is a healing area-of-effect device. When lit, it periodically pulses health to any agent standing within its radius. Out of the box it's a self-contained prop, but wiring it to Verse unlocks a full event-driven API:

  • React to proximity — know the moment a player steps into or out of the healing zone.
  • React to pulses — fire custom logic every time the campfire ticks health, or specifically when a named player receives a heal.
  • Control the fire — light it, extinguish it, and add wood to extend its burn time, all from code.
  • Track state changes — know when the fire is lit, put out, enabled, or disabled.

When to reach for it: Survival games (fire = safety), escort missions (campfire checkpoints), wave-defense games (healing station between rounds), or any scenario where a spatial healing zone needs scripted behavior.

API Reference

campfire_device

Used to place a campfire in the world that an agent can use to heal themselves.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).

campfire_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
AgentEntersEffectAreaEvent AgentEntersEffectAreaEvent<public>:listenable(agent) Signaled when an agent enters the area of effect for this device. Sends the entering agent.
AgentExitsEffectAreaEvent AgentExitsEffectAreaEvent<public>:listenable(agent) Signaled when an agent exits the area of effect for this device. Sends the exiting agent.
CampfirePulseEvent CampfirePulseEvent<public>:listenable(tuple()) Signaled when this device generates a pulse.
AgentPulsedEvent AgentPulsedEvent<public>:listenable(agent) Signaled when an agent is affected by a pulse generated by this device. Sends the affected agent.
LitEvent LitEvent<public>:listenable(agent) Signaled when this device is lit by an agent. Sends the lighting agent.
ExtinguishedEvent ExtinguishedEvent<public>:listenable(agent) Signaled when this device is extinguished by an agent. Sends the extinguishing agent.
EnabledEvent EnabledEvent<public>:listenable(tuple()) Signaled when this device is enabled.
DisabledEvent DisabledEvent<public>:listenable(tuple()) Signaled when this device is disabled.

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
AddWood AddWood<public>():void Adds wood to this device.
Light Light<public>(Agent:agent):void Lights this device.
Extinguish Extinguish<public>(Agent:agent):void Extinguishes this device.

Walkthrough

Scenario: A survival island has a central campfire. When a player enters the healing zone the campfire logs the arrival and adds extra wood so the fire burns longer. When the campfire is extinguished (by a storm mechanic or another player) a Verse device re-lights it after 10 seconds — keeping the safe zone alive but punishing players who let it die.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

# Attach this device to a campfire_device in the UEFN level.
campfire_manager := class(creative_device):

    # Wire this to your campfire_device in the Details panel.
    @editable
    Campfire : campfire_device = campfire_device{}

    # How long (seconds) to wait before re-lighting after extinguish.
    @editable
    RelightDelay : float = 10.0

    # We need a real agent to call Light/Extinguish — store the first
    # player who enters so we always have one on hand.
    var CachedAgent : ?agent = false

    OnBegin<override>()<suspends> : void =
        # Subscribe to all the events we care about.
        Campfire.AgentEntersEffectAreaEvent.Subscribe(OnPlayerEnter)
        Campfire.AgentExitsEffectAreaEvent.Subscribe(OnPlayerExit)
        Campfire.AgentPulsedEvent.Subscribe(OnPlayerHealed)
        Campfire.LitEvent.Subscribe(OnFireLit)
        Campfire.ExtinguishedEvent.Subscribe(OnFireExtinguished)

        # Make sure the fire starts lit by lighting it once we have
        # an agent — we'll do that reactively in OnPlayerEnter.
        # For now just ensure the device is enabled.
        Campfire.Enable()

    # Called when any agent walks into the campfire radius.
    OnPlayerEnter(Agent : agent) : void =
        # Cache the agent so we can call Light/Extinguish later.
        set CachedAgent = option{Agent}
        # Add wood every time someone enters — keeps the fire fuelled.
        Campfire.AddWood()

    # Called when any agent leaves the campfire radius.
    OnPlayerExit(Agent : agent) : void =
        # Nothing extra needed here — just a hook for your own logic.
        # Example: you could start a timer to extinguish if nobody remains.
        false

    # Called each time the campfire pulse heals a specific agent.
    OnPlayerHealed(Agent : agent) : void =
        # You could award bonus score, play a sound via another device, etc.
        false

    # Called when the fire is successfully lit.
    OnFireLit(Agent : agent) : void =
        # Great place to trigger a VFX spawner or play a sound cue.
        false

    # Called when the fire goes out — start the relight timer.
    OnFireExtinguished(Agent : agent) : void =
        spawn { RelightAfterDelay() }

    # Waits RelightDelay seconds then re-lights the campfire.
    RelightAfterDelay()<suspends> : void =
        Sleep(RelightDelay)
        # We need a valid agent to call Light().
        if (A := CachedAgent?):
            Campfire.Light(A)

Line-by-line breakdown:

Lines What's happening
@editable Campfire Exposes the campfire slot in the Details panel so you can drag-drop your placed device.
@editable RelightDelay Designers can tune the relight window without touching code.
var CachedAgent Light() and Extinguish() require an agent argument — we store the first entrant so we always have one.
Campfire.Enable() Ensures the device is active when the game starts.
Campfire.AgentEntersEffectAreaEvent.Subscribe(OnPlayerEnter) Hooks the enter event; handler signature must match (agent):void.
Campfire.AddWood() Called on every entry — each call extends burn time.
spawn { RelightAfterDelay() } Launches the relight coroutine without blocking the event handler.
Sleep(RelightDelay) Suspends the coroutine for the configured delay.
if (A := CachedAgent?): Safely unwraps the ?agent option before passing it to Light().

Common patterns

Pattern 1 — Disable the campfire between rounds and re-enable it fresh

In a wave-defense game you might want the campfire off during combat and on during the rest phase.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

campfire_round_controller := class(creative_device):

    @editable
    Campfire : campfire_device = campfire_device{}

    # Wire a trigger or button device here to signal round end.
    @editable
    RoundEndTrigger : trigger_device = trigger_device{}

    # Duration of the rest phase in seconds.
    @editable
    RestPhaseDuration : float = 30.0

    OnBegin<override>()<suspends> : void =
        # Campfire starts disabled — players haven't earned it yet.
        Campfire.Disable()
        RoundEndTrigger.TriggeredEvent.Subscribe(OnRoundEnd)

    OnRoundEnd(Agent : ?agent) : void =
        spawn { RunRestPhase() }

    RunRestPhase()<suspends> : void =
        # Enable the campfire and add a big wood boost for the rest phase.
        Campfire.Enable()
        Campfire.AddWood()
        Campfire.AddWood()
        Campfire.AddWood()
        # Wait out the rest phase, then disable again.
        Sleep(RestPhaseDuration)
        Campfire.Disable()

Key calls: Disable(), Enable(), AddWood() — three distinct methods in one flow.


Pattern 2 — Track which players are currently inside the healing zone

Useful for a game mode that awards bonus points only to players who stay near the fire.

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /Verse.org/Collections }

campfire_presence_tracker := class(creative_device):

    @editable
    Campfire : campfire_device = campfire_device{}

    # Simple counter — how many agents are currently in the zone.
    var AgentsInZone : int = 0

    OnBegin<override>()<suspends> : void =
        Campfire.AgentEntersEffectAreaEvent.Subscribe(OnEnter)
        Campfire.AgentExitsEffectAreaEvent.Subscribe(OnExit)
        Campfire.CampfirePulseEvent.Subscribe(OnPulse)

    OnEnter(Agent : agent) : void =
        set AgentsInZone = AgentsInZone + 1

    OnExit(Agent : agent) : void =
        if (AgentsInZone > 0):
            set AgentsInZone = AgentsInZone - 1

    # CampfirePulseEvent sends tuple() — no agent, just a tick signal.
    OnPulse(T : tuple()) : void =
        # Every pulse, if players are present, add more wood to keep it alive.
        if (AgentsInZone > 0):
            Campfire.AddWood()

Key calls: AgentEntersEffectAreaEvent, AgentExitsEffectAreaEvent, CampfirePulseEvent — note that CampfirePulseEvent is listenable(tuple()) so the handler takes (T : tuple()), not an agent.


Pattern 3 — Player-controlled extinguish and relight (interactive fire mechanic)

A player interacts with a button to toggle the campfire — useful for a puzzle where fire blocks a path.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

campfire_toggle_controller := class(creative_device):

    @editable
    Campfire : campfire_device = campfire_device{}

    # A button_device the player presses to toggle the fire.
    @editable
    ToggleButton : button_device = button_device{}

    var FireIsLit : logic = true

    OnBegin<override>()<suspends> : void =
        Campfire.LitEvent.Subscribe(OnLit)
        Campfire.ExtinguishedEvent.Subscribe(OnExtinguished)
        ToggleButton.InteractedWithEvent.Subscribe(OnButtonPressed)

    OnLit(Agent : agent) : void =
        set FireIsLit = true

    OnExtinguished(Agent : agent) : void =
        set FireIsLit = false

    OnButtonPressed(Agent : ?agent) : void =
        # Unwrap the optional agent before calling Light/Extinguish.
        if (A := Agent?):
            if (FireIsLit?):
                Campfire.Extinguish(A)
            else:
                Campfire.Light(A)

Key calls: Light(Agent), Extinguish(Agent), LitEvent, ExtinguishedEvent — demonstrates the full fire-state toggle loop.

Gotchas

1. Light() and Extinguish() require an agent — always have one ready

Light(Agent:agent) and Extinguish(Agent:agent) are not zero-argument calls. You must pass a valid agent. The safest pattern is to cache the first agent from AgentEntersEffectAreaEvent in a var CachedAgent : ?agent field and unwrap it with if (A := CachedAgent?): before calling either method. Calling these before any agent has entered (and before you've cached one) means you have no agent to pass — plan for that case.

2. CampfirePulseEvent sends tuple(), not an agent

The global pulse event fires on a timer regardless of who is nearby. Its handler signature is (T : tuple()) : void, not (Agent : agent) : void. If you want per-agent pulse data, subscribe to AgentPulsedEvent instead, which does send the healed agent.

3. AgentEntersEffectAreaEvent and AgentExitsEffectAreaEvent send agent, not ?agent

These two events are listenable(agent) — the handler receives a concrete agent, no optional unwrap needed. Contrast this with events on other devices (like trigger_device.TriggeredEvent) that send ?agent and require the if (A := Agent?): unwrap pattern. Don't add unnecessary unwrapping here.

4. EnabledEvent and DisabledEvent send tuple()

Like CampfirePulseEvent, the enable/disable state events carry no payload. Their handlers must be (T : tuple()) : void. A common mistake is writing (Agent : agent) : void for these — that won't compile.

5. AddWood() is additive, not absolute

Each call to AddWood() adds one unit of wood on top of whatever is already in the campfire. There is no SetWood(amount) call. If you want a large fuel boost, call AddWood() multiple times in a loop or in sequence. Calling it once per player entry is a common and effective pattern.

6. The device must be @editable — you cannot construct it in code

campfire_device is <concrete><final> and must be placed in the UEFN level editor. Declare it as an @editable field in your creative_device class and drag-drop the placed actor into the slot in the Details panel. A bare campfire_device{} default is only a placeholder — it won't refer to your placed device unless wired up in the editor.

7. spawn {} for async relight logic inside synchronous event handlers

Event handlers (like OnFireExtinguished) are synchronous — they cannot Sleep() directly. To run a timed relight, use spawn { MyCoroutine() } inside the handler to launch a concurrent task that can call Sleep() and then Light().

Device Settings & Options

The campfire_device User Options panel in the UEFN editor — every setting you can tune.

Campfire Device settings and options panel in the UEFN editor — Start Lit, Can Be Lit, Can Be Extinguished, Can Be Stoked, Campfire Zone Size, Health Per Pulse, Uses Wood, Wood Consumption Per Pulse, Max Wood Capacity, Starting Wood, Wood To Add On Trigger, Can Affect Vehicles, Affects Al, AIDamage Per Pulse, Use Advanced Lighting
Campfire Device — User Options in the UEFN editor: Start Lit, Can Be Lit, Can Be Extinguished, Can Be Stoked, Campfire Zone Size, Health Per Pulse, Uses Wood, Wood Consumption Per Pulse, Max Wood Capacity, Starting Wood, Wood To Add On Trigger, Can Affect Vehicles, Affects Al, AIDamage Per Pulse, Use Advanced Lighting
⚙️ Settings on this device (15)

Setting names read from the panel above — may be partial; the screenshots are the source of truth.

Start Lit
Can Be Lit
Can Be Extinguished
Can Be Stoked
Campfire Zone Size
Health Per Pulse
Uses Wood
Wood Consumption Per Pulse
Max Wood Capacity
Starting Wood
Wood To Add On Trigger
Can Affect Vehicles
Affects Al
AIDamage Per Pulse
Use Advanced Lighting

Guides & scripts that use campfire_device

Step-by-step tutorials that put this object to work.

Build your own lesson with campfire_device

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →