VerseIsland
Feed Learn Leaderboard Guides Reference Explore Search Docs Verse Library
Sign in
Feed Learn 📖 Codex Leaderboard Guides Reference Explore Search Docs Verse Library
Fortnite › Materials/VFX · Up to Fortnite · Materials/VFX · 58 of 211 in Materials/VFX
Browse Fortnite

Finalizing The Tagged Lights Puzzle Script

In this last step of the Tagged Lights Puzzle tutorial, you'll find the complete script for the puzzle and ideas to further change the example.

Complete Script

The following code is the complete script for a reusable puzzle that requires the player to find the right combination of lights by toggling their state with buttons.

|  |  |
| --- | --- |
|  | using { /Fortnite.com/Devices } |
|  | using { /Verse.org/Native } |
|  | using { /UnrealEngine.com/Temporary/Diagnostics } |
|  | using { /Verse.org/Simulation/Tags } |
|  | using { /Verse.org/Simulation } |
|  |  |
|  | # Derive from the `tag` class in the Verse.org/Simulation/Tags module to create a new Gameplay Tag. |
|  | puzzle_light := class(tag){} |
|  |  |
|  | log_tagged_lights_puzzle := class(log_channel){} |
|  |  |
|  | <# |
|  | You can use an instance of this class to subscribe to the |
|  | InteractedWithEvent of a button_device and have access to per-event properties (in this case, Indices and PuzzleDevice) in your event handler. |
|  | Think about it as each button having its personal state and event handler. |
|  | Since the class doesn’t have the <concrete> specifier, specifying default values for fields isn’t required. |
|  | #> |
|  | button_event_handler := class(): |
|  | # Positions used to access the lights this button controls. |
|  | Indices : []int |
|  |  |
|  | # tagged_lights_puzzle that created this button_event_handler so we can call functions on it. |
|  | PuzzleDevice : tagged_lights_puzzle |
|  |  |
|  | OnButtonPressed(InPlayer : agent) : void = |
|  | # Tell the PuzzleDevice to toggle the lights at the positions this button controls. |
|  | PuzzleDevice.ToggleLights(Indices) |
|  |  |
|  | tagged_lights_puzzle := class<concrete>(creative_device): |
|  | Logger : log = log{Channel := log_tagged_lights_puzzle} |
|  |  |
|  | # Buttons the player uses to interact with the puzzle. |
|  | @editable |
|  | Buttons : []button_device = array{} |
|  |  |
|  | <# |
|  | The number of elements in ButtonsToLights should match the number of elements in Buttons. |
|  | Each zero-indexed array of indices describes which lights the button at Buttons[x] toggles (where 'x' is the button index). |
|  | For example, Buttons[2] toggles the first and second light, as specified by array{0,1}. |
|  | #> |
|  | ButtonsToLights : [][]int = array{array{0, 3}, array{0, 1, 2}, array{0, 1}, array{1}} |
|  |  |
|  | <# |
|  | The LightsState logic array is used to keep track of the on-off state of all lights. |
|  | It's also used to set the initial state of the lights, so its number of elements |
|  | should match the number of lights tagged with the puzzle_light tag. |
|  | #> |
|  | @editable |
|  | var LightsState : []logic = array{false, false, false, false} |
|  |  |
|  | <# |
|  | The puzzle is solved when LightsState matches SolvedLightsState. |
|  | This means that SolvedLightsState should have as many elements as LightsState. |
|  | #> |
|  | @editable |
|  | SolvedLightsState : []logic = array{true, true, true, true} |
|  |  |
|  | @editable |
|  | # This ItemSpawner is enabled when the puzzle is solved. |
|  | ItemSpawner : item_spawner_device = item_spawner_device{} |
|  |  |
|  | # Holds the lights found via gameplay tags. |
|  | var Lights : []customizable_light_device = array{} |
|  |  |
|  | # Holds the handlers for each button's InteractedWithEvent to allow unsubscribing from the event once the puzzle is solved. |
|  | var ButtonSubscriptions : []cancelable = array{} |
|  |  |
|  | OnBegin<override>()<suspends> : void = |
|  | SetupPuzzleLights() |
|  |  |
|  | <# |
|  | For each button and its index, if it has valid LightsIndices values, |
|  | create a new button_event_handler with the Indices it uses and a reference to this tagged_light_puzzle (Self). |
|  | Use the handler's OnButtonPressed function to Subscribe to the Button's InteractedWithEvent. |
|  | Save these subscriptions in the ButtonSubscriptions array to cancel the subscription later so the player can't interact with the puzzle once it's solved. |
|  | #> |
|  | set ButtonSubscriptions = for: |
|  | ButtonIndex -> Button : Buttons |
|  | LightIndices := ButtonsToLights[ButtonIndex] |
|  | do: |
|  | Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) |
|  |  |
|  | SetupPuzzleLights() : void = |
|  | # Keep in mind that the devices are not guaranteed any specific order when retrieved via gameplay tags. |
|  | TaggedActors := GetCreativeObjectsWithTag(puzzle_light{}) |
|  | <# |
|  | For each actor with the puzzle_light tag, check if it's a customizable_light_device by trying to cast it to that type. |
|  | If it is, get its initial LightState to TurnOn() or TurnOff() the LightDevice. |
|  | Save all the tagged customizable_light_device in the Lights array. |
|  | #> |
|  | set Lights = for: |
|  | ActorIndex -> TaggedActor : TaggedActors |
|  | LightDevice := customizable_light_device[TaggedActor] |
|  | ShouldLightBeOn := LightsState[ActorIndex] |
|  | do: |
|  | Logger.Print("Adding Light at index {ActorIndex} with State:{if (ShouldLightBeOn?) then "On" else "Off"}") |
|  |  |
|  | if (ShouldLightBeOn?) then LightDevice.TurnOn() else LightDevice.TurnOff() |
|  | LightDevice # The last statement of an expression is its result value. `for` expressions return all the values in an array. |
|  |  |
|  | ToggleLights(LightIndices : []int) : void = |
|  | <# |
|  | For each Index, get the corresponding LightState and reference to the Light device. |
|  | If they're both valid, determine IsLightOn from the current LightState (if on->off ; if off->on) and |
|  | set the corresponding LighsState[Index] to IsLightOn. |
|  | #> |
|  | for: |
|  | LightIndex : LightIndices |
|  | IsLightOn := LightsState[LightIndex] |
|  | Light := Lights[LightIndex] |
|  | do: |
|  | <# |
|  | To negate a boolean value in Verse: if (MyLogic?) {false} else {true} |
|  | Here, we also TurnOff() or TurnOn() the Light before returning the negated value. |
|  | #> |
|  | Logger.Print("Turning light at index {LightIndex} {if (IsLightOn?) then "Off" else "On"}") |
|  | NewLightState := |
|  | if (IsLightOn?): |
|  | Light.TurnOff() |
|  | false |
|  | else: |
|  | Light.TurnOn() |
|  | true |
|  | if (set LightsState[LightIndex] = NewLightState): # Array indexing may fail, so it must be wrapped in a failure context. |
|  | Logger.Print("Updated the state for light at {LightIndex}") |
|  |  |
|  | # LightsState might have changed, so check if the puzzle is solved. |
|  | if (IsPuzzleSolved[]): |
|  | Logger.Print("Puzzle solved!") |
|  |  |
|  | ItemSpawner.Enable() |
|  |  |
|  | # Unsubscribe/Cancel all event handlers so the player can't toggle lights anymore. |
|  | for (ButtonSubscription : ButtonSubscriptions): |
|  | ButtonSubscription.Cancel() |
|  |  |
|  | <# |
|  | A function with the <decides> effect can only be used in a failure context like `if (IsPuzzleSolved[])`. |
|  | Notice the function call with [] instead of () for failable function calls. |
|  | #> |
|  | IsPuzzleSolved()<decides><transacts> : void = |
|  | <# |
|  | Iterate each LightsState and check if it matches its SolvedLightsState. |
|  | The first time the `for` inner block fails, the function fails and |
|  | the failure bubbles up to the caller. |
|  | Otherwise, the function succeeds. |
|  | #> |
|  | for: |
|  | LightIndex -> IsLightOn : LightsState |
|  | IsLightOnInSolution := SolvedLightsState[LightIndex] |
|  | do: |
|  | IsLightOn = IsLightOnInSolution |

You're reading a preview

The full reference is free for BrainDeadGuild Discord members — sign in to read it all, or open the original at the source.

Sign in with Discord — free for members Read the original at Epic Games

Sign in with your BrainDead.TV / BrainDeadGuild Discord account for full access.

Comments

    Sign in to vote, comment, or suggest an edit. Sign in
    📄
    Source
    Epic Games

    © Epic Games. Official Epic developer documentation, shown here as a reference with a link to the original. All rights remain with Epic Games. Terms ↗

    View original Sources & licensing
    Request removal
    Last updated May 12, 2026
    Keep exploring
    More in Materials/VFX · 58 of 211
    Prev
    tagged lights 5 detecting when the puzzle is solved in verse
    Next
    tagged lights puzzle in verse
    Browse all files in this folder (A–Z)
    Next up
    • In this last step of the [Tagged Lights Puzzle
    • Tagged Lights 6 Final Result For Tagged Lights Puzzle In Verse
    Related topics
    • Gameplay Tags In Verse Verse Language
    • Gameplay Tags In Verse Verse Language
    • Verse Tags In Verse Verse Language
    • Verse Tags In Fortnite Verse Language
    • Tagged Lights Puzzle In Verse Materials/Vfx

    Related

    Open in graph →

    Linked docs

    • Tagged Lights Puzzle In Verse

    Related topics

    • Gameplay Tags In Verse
    • Gameplay Tags In Verse
    • Verse Tags In Verse
    • Verse Tags In Fortnite
    VerseIsland · an archipelago of Verse & UEFN knowledge
    🗺️ Island atlas Learn Guides History About & Press Sources & Licensing Status

    Not affiliated with Epic Games. Fortnite, UEFN, Unreal Engine, and Verse are trademarks of Epic Games, Inc. Content is attributed to its source — see Sources & Licensing.

    🦜

    Scout · your island guide

    The Isle of Verse