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
notis not a boolean — it inverts success/failure.not (X > 0)succeeds when the comparison fails. It is NOT!XorX == false. To test alogicvariable, query it:not (Flag?)succeeds whenFlagisfalse.- Bindings introduced under
notare out of scope afterward. Innot (Enemy := GetNearest[]),Enemycannot be used in thethenbranch —notsucceeding means the binding failed, so there is nothing to reference. messageneeds a localized value. EveryShow/SetTextcall takesmessage, never a raw string. Declare a<localizes>helper likeAnnounce<localizes>(S:string):message = "{S}"and passAnnounce("...").SpawnAtis<suspends>and returns agent-or-false. Call it insideOnBegin(which is<suspends>) or another suspends context, and always handle the failure — eitherif (A := Spawner.SpawnAt(...))to count success orif (not (_ := Spawner.SpawnAt(...)))to detect the cap.Show()with no args vsShow(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.DisplayTimeof0.0is persistent. Comparing withnot (T = 0.0)is the clean way to ask 'is this message NOT persistent?' before hiding it.