Overview
The switch_device is the classic on/off lever. A player walks up, interacts, and the switch flips between two states — on and off. That single bit of state is incredibly useful: it can power a barrier, reveal a path, flip a light, or be one piece of a multi-switch puzzle (the escape-room circuit-breaker pattern).
Reach for a switch when you want a player-controlled toggle rather than a one-shot button press. Unlike a button, a switch remembers whether it is on or off, can store that state per-player or globally, can persist across sessions, and can auto-reset after a timer. In Verse you don't poll the device — you subscribe to TurnedOnEvent and TurnedOffEvent and run your logic in the handlers, and you call methods like TurnOn, TurnOff, ToggleState, SetState and CheckState to drive or query it from code.
A few key concepts before we code:
- Every state-changing method takes an
Agent— the instigator of the action (the player flipping it). Events hand you that agent back. GetCurrentState()is a failable query (<decides>): it succeeds when the switch is on and fails when it is off. You use it inside anif.- The device has a Store State Per Player setting. If it's No, use the no-arg overloads (
GetCurrentState(),SetState(State)). If it's Yes, use the agent overloads (GetCurrentState(Agent),SetState(Agent, State)).
API Reference
switch_device
Used to allow agents to turn other linked devices on/off or other custom state changes.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
switch_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
TurnedOnEvent |
TurnedOnEvent<public>:listenable(agent) |
Signaled when the switch is turned on by the specified agent. Sends the agent that turned on the device. |
TurnedOffEvent |
TurnedOffEvent<public>:listenable(agent) |
Signaled when the switch is turned off by the specified agent. Sends the agent that turned off the device. |
IfOnWhenCheckedEvent |
IfOnWhenCheckedEvent<public>:listenable(tuple()) |
Signaled if the switch is on when the state is checked. |
IfOffWhenCheckedEvent |
IfOffWhenCheckedEvent<public>:listenable(tuple()) |
Signaled if the switch is off when the state is checked. |
StateSaveEvent |
StateSaveEvent<public>:listenable(tuple()) |
Signaled when the switch state is saved. |
StateChangesEvent |
StateChangesEvent<public>:listenable(tuple()) |
Signaled when the switch state changes. |
StateLoadEvent |
StateLoadEvent<public>:listenable(agent) |
Signaled when the switch state is loaded by the specified agent. Sends the agent that loaded the state on the device. |
ClearEvent |
ClearEvent<public>:listenable(agent) |
Signaled when the persistent data is cleared by the specified agent. Sends the agent that cleared persistent data on the device. |
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. |
TurnOn |
TurnOn<public>(Agent:agent):void |
Turns on this device with Agent acting as the instigator of the action. |
TurnOff |
TurnOff<public>(Agent:agent):void |
Turns off the device with Agent acting as the instigator of the action. |
ToggleState |
ToggleState<public>(Agent:agent):void |
Toggles between TurnOn and TurnOff with Agent acting as the instigator of the action. |
LoadState |
LoadState<public>(Agent:agent):void |
Loads the device state with Agent acting as the instigator of the action. |
SaveState |
SaveState<public>(Agent:agent):void |
Saves the device state with Agent acting as the instigator of the action. |
LoadStateForAll |
LoadStateForAll<public>():void |
Loads the device state for all players. |
SaveStateForAll |
SaveStateForAll<public>():void |
Saves the device state for all players |
CheckState |
CheckState<public>(Agent:agent):void |
Checks the device state with Agent acting as the instigator of the action. |
ClearPersistenceData |
ClearPersistenceData<public>(Agent:agent):void |
Clears persistence data for Agent. |
ClearAllPersistenceData |
ClearAllPersistenceData<public>():void |
Clears persistence data for all agents. |
GetCurrentState |
GetCurrentState<public>(Agent:agent)<transacts><decides>:void |
Succeeds if the current state of this switch is on, fails otherwise. Use this overload of GetCurrentState when this device has Store State Per Player set to Yes. |
GetCurrentState |
GetCurrentState<public>()<transacts><decides>:void |
Succeeds if the current state of this switch is on, fails otherwise. Use this overload of GetCurrentState when this device has Store State Per Player set to No. |
IsStatePerAgent |
IsStatePerAgent<public>()<transacts><decides>:void |
Query whether this device has a single global on/off state, or has a personalized on/off state for each individual agent. |
SetInteractionTime |
SetInteractionTime<public>(Time:float):void |
Sets the Interaction Time required to activate this device (in seconds). |
GetInteractionTime |
GetInteractionTime<public>()<transacts>:float |
Returns the Interaction Time required to activate this device (in seconds). |
SetTurnOnInteractionText |
SetTurnOnInteractionText<public>(Text:message):void |
Sets the Turn On Text to be displayed to a user when the switch is currently off, and offers an interaction to switch it on. Clamped to 150 characters. |
SetTurnOffInteractionText |
SetTurnOffInteractionText<public>(Text:message):void |
Sets the Turn Off Text to be displayed to a user when the switch is currently on, and offers an interaction to switch it off. Clamped to 150 characters. |
SetState |
SetState<public>(Agent:agent, State:logic):void |
Sets the state of the switch to a specific value for a specific Agent. Use when the device has Store State Per Player set to Yes. |
SetState |
SetState<public>(State:logic):void |
Sets the state of the switch to a specific value. Use when the device has Store State Per Player set to No. |
SetStateResetTime |
SetStateResetTime<public>(Time:float):void |
Updates the State Reset Time for the device, in seconds, clamped to the Min and Max defined in the device. This will not apply to any state reset timers currently in effect. Set to 0.0 to disable the State Reset Time. Set to less than 0.0 |
SetStateResetTime |
SetStateResetTime<public>(Agent:agent, Time:float):void |
Updates the State Reset Time for the device, in seconds,for a specific player (if Store State Per Player is Yes), clamped to the Min and Max defined in the device. This will not apply to any state reset timers currently in effect. Set |
GetStateResetTime |
GetStateResetTime<public>()<transacts>:float |
Returns the value of State Reset Time, in seconds, for the device. Returns -1.0 if State Reset Time is not used. |
GetStateResetTime |
GetStateResetTime<public>(Agent:agent)<transacts>:float |
Returns the value of State Reset Time, in seconds, for the device, for a specific player. Returns -1.0 if State Reset Time is not used. |
GetCurrentResetTime |
GetCurrentResetTime<public>():float |
Returns the time, in seconds, before the switch will reset itself to default. Returns -1.0 if Store State Per Player is Yes or if there is no active reset timer. |
GetCurrentResetTime |
GetCurrentResetTime<public>(Agent:agent):float |
Returns the time, in seconds, before the switch will reset itself to default for Agent. Returns -1.0 if there is no active reset timer. |
Walkthrough
Let's build a vault door power switch. A player flips a wall switch (the switch_device). When it turns on, we power up a barrier_device so players can pass, play a confirmation audio_player_device, and update the interaction prompt. When it turns off, we slam the barrier back up. We also set a custom interaction time and prompt text in code so the device feels right.
# Vault door controlled by a wall switch.
vault_power_switch := class(creative_device):
# The wall switch the player interacts with.
@editable
PowerSwitch : switch_device = switch_device{}
# The barrier blocking the vault; we drop it when powered on.
@editable
VaultBarrier : barrier_device = barrier_device{}
# Plays a confirmation sound when power comes on.
@editable
PowerOnSound : audio_player_device = audio_player_device{}
# Localized message helper — `message` params need a localized value.
PromptText<localizes>(S : string) : message = "{S}"
OnBegin<override>()<suspends> : void =
# Configure the switch from code before players touch it.
PowerSwitch.SetInteractionTime(1.5)
PowerSwitch.SetTurnOnInteractionText(PromptText("Restore Vault Power"))
PowerSwitch.SetTurnOffInteractionText(PromptText("Cut Vault Power"))
# Make sure the door starts sealed.
VaultBarrier.Enable()
# React to the player flipping the switch.
PowerSwitch.TurnedOnEvent.Subscribe(OnPowerOn)
PowerSwitch.TurnedOffEvent.Subscribe(OnPowerOff)
# Called when an agent turns the switch ON.
OnPowerOn(Agent : agent) : void =
# Drop the barrier so the vault opens.
VaultBarrier.Disable()
PowerOnSound.Play(Agent)
# Called when an agent turns the switch OFF.
OnPowerOff(Agent : agent) : void =
# Re-seal the vault.
VaultBarrier.Enable()
Line by line:
@editable PowerSwitch : switch_device = switch_device{}— you MUST declare the placed device as an editable field so Verse can talk to the one you dropped in the level. A bareswitch_device.TurnOn()would be an Unknown identifier error.PromptText<localizes>(S : string) : message— theSetTurnOnInteractionText/SetTurnOffInteractionTextmethods take amessage, not a raw string. This helper wraps a string into a localizedmessage. There is noStringToMessage.- In
OnBegin,SetInteractionTime(1.5)makes the player hold for 1.5 seconds; the twoSet...InteractionTextcalls give context-aware prompts (one shown while off, one while on). VaultBarrier.Enable()seals the door at match start.PowerSwitch.TurnedOnEvent.Subscribe(OnPowerOn)wires the switch's turned on event to our method.TurnedOnEventis alistenable(agent), so the handler signature is(Agent : agent).OnPowerOn/OnPowerOffare methods at class scope (4-space indent). When power comes on weDisable()the barrier (opening the vault) andPlaythe sound for the instigating agent; when it goes off we re-Enable()the barrier.
Common patterns
Toggle a switch from another device, and query its state
Here a separate trigger (a pressure plate) toggles the switch, and we read the result with the failable GetCurrentState(). This is a global switch (Store State Per Player = No), so we use the no-arg overloads.
lights_toggle := class(creative_device):
@editable
LightSwitch : switch_device = switch_device{}
@editable
PressurePlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# Each time the plate fires, flip the switch for that player.
PressurePlate.TriggeredEvent.Subscribe(OnPlateStepped)
OnPlateStepped(MaybeAgent : ?agent) : void =
# listenable(?agent) hands an optional agent — unwrap it.
if (A := MaybeAgent?):
LightSwitch.ToggleState(A)
# GetCurrentState() succeeds only when the switch is ON.
if (LightSwitch.GetCurrentState[]):
Print("Lights are now ON")
else:
Print("Lights are now OFF")
Force a state in code and auto-reset it
Useful for round resets: drive the switch directly with SetState, give it a reset timer with SetStateResetTime, and listen for the change with StateChangesEvent.
round_reset_switch := class(creative_device):
@editable
GlobalSwitch : switch_device = switch_device{}
OnBegin<override>()<suspends> : void =
# Force the switch OFF at the start of a round (global overload).
GlobalSwitch.SetState(false)
# Have it reset itself to default after 30 seconds.
GlobalSwitch.SetStateResetTime(30.0)
# React whenever the state changes for any reason.
GlobalSwitch.StateChangesEvent.Subscribe(OnStateChanged)
OnStateChanged() : void =
# StateChangesEvent is listenable(tuple()) — no agent payload.
Print("Switch state changed; reset countdown is running")
Save & load per-player state (persistence)
When Store State Per Player is Yes, you can persist each player's switch position. Subscribe to StateLoadEvent and use SaveState / LoadState with an agent.
per_player_switch := class(creative_device):
@editable
DoorSwitch : switch_device = switch_device{}
@editable
JoinTracker : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# When the player's saved state loads, react to it.
DoorSwitch.StateLoadEvent.Subscribe(OnStateLoaded)
# Persist whatever the player set when they flip it on.
DoorSwitch.TurnedOnEvent.Subscribe(OnTurnedOn)
OnTurnedOn(Agent : agent) : void =
# Save this player's switch state to persistence.
DoorSwitch.SaveState(Agent)
OnStateLoaded(Agent : agent) : void =
# Per-player overload of GetCurrentState takes the agent.
if (DoorSwitch.GetCurrentState[Agent]):
Print("This player's switch loaded ON")
else:
Print("This player's switch loaded OFF")
Gotchas
GetCurrentStateis failable, not a getter that returns a bool. It has the<decides>effect: it succeeds if the switch is on and fails if off. Call it inside anif (Switch.GetCurrentState[]):(square brackets for the failable call). There is noGetCurrentState()that returns alogicvalue.- Pick the right overload for your Store State Per Player setting. With per-player = No, use
GetCurrentState[],SetState(State),GetStateResetTime(). With per-player = Yes, use the agent versions:GetCurrentState[Agent],SetState(Agent, State),GetCurrentResetTime(Agent). Mixing them gives wrong (or empty) results — e.g.GetCurrentResetTime()returns-1.0when the device is per-player. - Interaction text must be a
message.SetTurnOnInteractionText/SetTurnOffInteractionTextwon't accept a plain string. Use a<localizes>helper likePromptText<localizes>(S:string):message = "{S}". Text is clamped to 150 characters. tuple()events carry no agent.IfOnWhenCheckedEvent,IfOffWhenCheckedEvent,StateChangesEvent,StateSaveEventarelistenable(tuple())— their handlers take no parameters. OnlyTurnedOnEvent,TurnedOffEvent,StateLoadEventandClearEventhand you anagent.CheckStatedoesn't return the state — it raises events. CallingCheckState(Agent)fires eitherIfOnWhenCheckedEventorIfOffWhenCheckedEvent. Subscribe to those if you trigger checks from code (the escape-room circuit-breaker puzzle reads switch sequences this way).- Trigger payloads are optional agents.
trigger_device.TriggeredEventislistenable(?agent), so unwrap withif (A := MaybeAgent?):before passing it toToggleState(A). Switch events themselves arelistenable(agent)and need no unwrapping. - Verse never auto-converts int↔float.
SetInteractionTimeandSetStateResetTimetakefloat— write1.5and30.0, not30.