Reference Verse

logic not: Inverting Success on the Cove

On a sunny cel-shaded cove, the fun starts when the pirates are gone — not before. Verse's `not` operator flips success into failure and failure into success, letting you say 'when there are NO enemies left, open the treasure.' In this article we wire `not` into a creature_spawner_device and a hud_message_device to build a beach ambush that pays off only when the coast is clear.

Updated
The code on this reference page is provided as-is and did not pass the latest compile check — treat the examples as a starting point and verify in your project.
Watch the Knotcreature_spawner_device in ~90 seconds.

Overview

not is one of Verse's three logic-of-failure operators (and, or, not). It doesn't return a boolean — it inverts success and failure. If an expression succeeds, not (expression) fails; if the expression fails, not (expression) succeeds. That makes it perfect for gameplay questions phrased in the negative: "when the wave is NOT still spawning...", "if the player does NOT already have the key...", "when there are NO living creatures left."

On our sunny cove that means: pirates (creatures) rush the dock from a creature_spawner_device, and a hud_message_device counts them. Only when we can prove there are not any pirates left do we flash the victory banner. not also pairs beautifully with a plain logic variable — not (WaveActive?) succeeds exactly when WaveActive is false, so you never have to write clumsy == false comparisons.

Reach for not whenever the absence of something is the trigger: no enemies, no lock, no key, not yet started.

API Reference

creature_spawner_device

Used to spawn one or more waves of creatures of customizable types at selected time intervals.

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

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

Events (subscribe a handler to react):

Event Signature Description
SpawnedEvent SpawnedEvent<public>:listenable(agent) Signaled when a creature is spawned. Sends the agent creature who was spawned.
EliminatedEvent EliminatedEvent<public>:listenable(device_ai_interaction_result) Signaled when a creature is eliminated. Source is the agent that has eliminated the creature. If the creature was eliminated by a non-agent then Source is 'false'. Target is the creature that was eliminated.

Methods (call these to make the device act):

Method Signature Description
SpawnAt SpawnAt<public>(Position:(/Verse.org/SpatialMath:)vector3, ?Rotation:?(/Verse.org/SpatialMath:)rotation Spawn a creature at the given position. When Rotation is not provided, it will default to the Device's rotation. Returns the agent spawned or false if the device has reached its maximum spawn count. This function is <suspends> because it
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
DestroySpawner DestroySpawner<public>():void Destroys this device.
EliminateCreatures EliminateCreatures<public>():void Eliminates all creatures spawned by this device.
GetSpawnLimit GetSpawnLimit<public>()<transacts>:int Returns the spawn limit of the device.

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

Here's the full cove ambush. Stepping into OnBegin, we enable the spawner, spawn a wave of pirates at the dock, and keep a running count. Each time a pirate is eliminated we decrement the count; when we can prove there are not any pirates left AND the wave is not still active, we show the victory HUD message.

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

cove_ambush := class(creative_device):

    @editable
    PirateSpawner : creature_spawner_device = creature_spawner_device{}

    @editable
    Banner : hud_message_device = hud_message_device{}

    # A localized message wrapper — message params never take raw strings.
    Announce<localizes>(S : string) : message = "{S}"

    # Running count of pirates still standing.
    var LivingPirates : int = 0

    # Is a wave currently being spawned?
    var WaveActive : logic = false

    OnBegin<override>()<suspends> : void =
        # React to spawn / elimination as they happen.
        PirateSpawner.SpawnedEvent.Subscribe(OnPirateSpawned)
        PirateSpawner.EliminatedEvent.Subscribe(OnPirateEliminated)

        PirateSpawner.Enable()
        Banner.SetDisplayTime(4.0)
        Banner.Show(Announce("Pirates are storming the dock!"))

        # Spawn a small wave right at the spawner's location.
        set WaveActive = true
        DockPos := PirateSpawner.GetTransform().Translation
        WaveSize := GetRandomInt(3, 5)
        var Index : int = 0
        loop:
            if (Index >= WaveSize):
                break
            # SpawnAt suspends; bind and test the optional result safely.
            SpawnedAgent := PirateSpawner.SpawnAt((DockPos, none))
            if (SpawnedAgent?):
                set LivingPirates = LivingPirates + 1
            set Index = Index + 1
        set WaveActive = false

    # Called each time a creature appears.
    OnPirateSpawned(Creature : agent) : void =
        Banner.SetText(Announce("A pirate landed!"))
        Banner.Show()

    # Called each time a creature dies.
    OnPirateEliminated(Result : device_ai_interaction_result) : void =
        set LivingPirates = LivingPirates - 1
        CheckCoastClear()

    # Victory only when there are NOT any pirates left and the wave is NOT still spawning.
    CheckCoastClear() : void =
        if (LivingPirates = 0 and WaveActive?):
            Banner.SetDisplayTime(6.0)
            Banner.Show(Announce("The coast is clear! Grab the treasure!"))```

**Line by line:**
- `PirateSpawner` and `Banner` are `@editable` fields  the only way to reference placed devices. Bind them to the spawner and HUD device in the UEFN details panel.
- `Announce<localizes>` turns a plain string into the `message` type that `Show`/`SetText` require. There is no `StringToMessage`.
- `var LivingPirates` and `var WaveActive : logic` track game state. `WaveActive` starts `false`.
- In `OnBegin` we subscribe our two handler methods to the spawner's real events, then `Enable()` the device.
- `GetRandomInt(3, 5)` picks a wave size; the `loop` calls `SpawnAt` (a `<suspends>` method) once per pirate. `?Rotation := false` means "use the device's rotation." We `if (_ := ...)` because `SpawnAt` returns agent-or-false — only count a success.
- `OnPirateEliminated` decrements the count and calls `CheckCoastClear`.
- The payoff: `not (LivingPirates > 0)` **succeeds when the count is 0 or less** (the `> 0` query fails, `not` flips it to success). `not (WaveActive?)` **succeeds when `WaveActive` is `false`**. Combined with `and`, the banner only appears when both are true — the coast is genuinely clear.

## Common patterns

### 1. `not` guarding a HUD nudge — only warn players who don't already see the message

Here we use `not` with a `logic` flag so the "Enemies incoming" banner fires exactly once. `EliminateCreatures` clears the wave when a reset trigger fires.

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

warn_once_device := class(creative_device):

    @editable
    Spawner : creature_spawner_device = creature_spawner_device{}

    @editable
    Warning : hud_message_device = hud_message_device{}

    Line<localizes>(S : string) : message = "{S}"

    var WarningShown : logic = false

    OnBegin<override>()<suspends> : void =
        Spawner.SpawnedEvent.Subscribe(OnSpawned)
        Spawner.Enable()

    OnSpawned(Creature : agent) : void =
        # Only show the banner if we have NOT shown it yet.
        if (not (WarningShown?)):
            set WarningShown = true
            Warning.SetText(Line("Enemies incoming  hold the shore!"))
            Warning.Show()
            # Optional: wipe the wave for a fresh start elsewhere.
            Spawner.EliminateCreatures()

2. not on a failable spawn — react when the limit is NOT reached

SpawnAt returns false when the spawn cap is hit. We use GetSpawnLimit for the HUD text and not to decide whether to keep going.

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

spawn_until_full := class(creative_device):

    @editable
    Spawner : creature_spawner_device = creature_spawner_device{}

    @editable
    Status : hud_message_device = hud_message_device{}

    Info<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        Spawner.Enable()
        Limit := Spawner.GetSpawnLimit()
        Status.SetDisplayTime(0.0)
        Status.Show(Info("Filling the cove... limit is {Limit}"))

        Pos := Spawner.GetTransform().Translation
        loop:
            # If SpawnAt does NOT succeed, the cap is reached — stop.
            if (not (_ := Spawner.SpawnAt(Pos, ?Rotation := false))):
                Status.Show(Info("The cove is full!"))
                break
            Sleep(1.5)

3. not before a cleanup — hide and clear only if the banner is NOT meant to persist

Using DestroySpawner, Hide, and ClearAllMessages behind a not guard so we don't tear things down while a persistent message is up.

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

cove_cleanup := class(creative_device):

    @editable
    Spawner : creature_spawner_device = creature_spawner_device{}

    @editable
    Banner : hud_message_device = hud_message_device{}

    OnBegin<override>()<suspends> : void =
        DisplayTime := Banner.GetDisplayTime()
        # 0.0 means persistent. Only clean up when it is NOT persistent.
        if (not (DisplayTime = 0.0)):
            Banner.Hide()
            Banner.ClearAllMessages()
            Spawner.EliminateCreatures()
            Spawner.DestroySpawner()

Gotchas

  • not is not a boolean — it inverts success/failure. not (X > 0) succeeds when the comparison fails. It is NOT !X or X == false. To test a logic variable, query it: not (Flag?) succeeds when Flag is false.
  • Bindings introduced under not are out of scope afterward. In not (Enemy := GetNearest[]), Enemy cannot be used in the then branch — not succeeding means the binding failed, so there is nothing to reference.
  • message needs a localized value. Every Show/SetText call takes message, never a raw string. Declare a <localizes> helper like Announce<localizes>(S:string):message = "{S}" and pass Announce("...").
  • SpawnAt is <suspends> and returns agent-or-false. Call it inside OnBegin (which is <suspends>) or another suspends context, and always handle the failure — either if (A := Spawner.SpawnAt(...)) to count success or if (not (_ := Spawner.SpawnAt(...))) to detect the cap.
  • Show() with no args vs Show(Agent). The parameterless overload shows to everyone; the agent overload targets one player. Pick the one matching how the device is configured, or you'll show messages to the wrong screens.
  • DisplayTime of 0.0 is persistent. Comparing with not (T = 0.0) is the clean way to ask 'is this message NOT persistent?' before hiding it.

Guides & scripts that use creature_spawner_device

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

Build your own lesson with creature_spawner_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 →