Overview
The note_progressor_device is part of Fortnite's Patchwork music system. Its job is to transpose the notes flowing through your Patchwork graph so they follow a chord progression you author in the device's options. A note sequencer or live player input feeds raw notes in; the progressor shifts each one onto the nearest chord tone of whatever step the progression is on. The result is a melody that always stays in key as the harmony moves underneath it.
Like every Patchwork device, it inherits from patchwork_device, which means the only behavior Verse exposes is Enable() and Disable(). The musical content (the chords, the timing, the progression steps) is configured in the UEFN Details panel — Verse is the switch that decides whether the progressor is participating in the mix right now.
Reach for this when you want adaptive, in-key music: silence the harmony transposition during a stealth section, then turn it back on the instant combat begins. Because Enable/Disable are plain calls with no agent and no return, the device pairs naturally with triggers, buttons, and round events.
API Reference
note_progressor_device
Transpose Patchwork note inputs to follow a chord progression.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from patchwork_device.
note_progressor_device<public> := class<concrete><final>(patchwork_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. |
Walkthrough
Scenario: A boss arena. When a player steps on the trigger plate in front of the boss door, the music should "come alive" — we enable the Note Progressor so the looping melody starts following the dramatic chord progression. When a second trigger (the exit) fires, we disable it so the music falls back to its flat, calm state.
We declare the progressor and two triggers as @editable fields, subscribe to each trigger's TriggeredEvent in OnBegin, and call Enable/Disable from the handlers.
note_progressor_boss_arena := class(creative_device):
# The Patchwork Note Progressor placed in the level.
@editable
Progressor : note_progressor_device = note_progressor_device{}
# Player steps here to start the fight -> music comes alive.
@editable
StartPlate : trigger_device = trigger_device{}
# Player steps here to leave -> music goes calm.
@editable
ExitPlate : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# Start the encounter with the progression OFF (calm music).
Progressor.Disable()
# Wire each plate to its handler.
StartPlate.TriggeredEvent.Subscribe(OnStartStepped)
ExitPlate.TriggeredEvent.Subscribe(OnExitStepped)
# TriggeredEvent hands us a ?agent; unwrap it before use.
OnStartStepped(Agent : ?agent) : void =
if (Player := Agent?):
# Turn the chord progression on — melody now follows the chords.
Progressor.Enable()
OnExitStepped(Agent : ?agent) : void =
if (Player := Agent?):
# Drop back to flat, untransposed notes.
Progressor.Disable()
Line by line:
class(creative_device)— every script that touches placed devices is a creative device.@editable Progressor : note_progressor_device = note_progressor_device{}— this field is the only way to talk to the placed progressor; in UEFN you'll bind it to the actual device in the level. Callingnote_progressor_device{}.Enable()on a bare literal would do nothing useful, so we bind via the editable.- The two trigger fields work the same way.
- In
OnBegin,Progressor.Disable()guarantees a known starting state — the music is calm until a player commits to the fight. StartPlate.TriggeredEvent.Subscribe(OnStartStepped)registers a method of this class as the handler. Subscriptions belong inOnBegin.TriggeredEventis alistenable(?agent), so each handler receives(Agent : ?agent).if (Player := Agent?):unwraps the optional — we only proceed when a real agent triggered the plate.Progressor.Enable()/Progressor.Disable()are the real device calls that make the harmony start or stop following the progression.
Common patterns
Pattern 1 — Button toggles the progression on
A jukebox button in a social hub: press it once to switch the adaptive harmony on. Uses InteractedWithEvent and Enable.
note_progressor_jukebox := class(creative_device):
@editable
Progressor : note_progressor_device = note_progressor_device{}
@editable
MusicButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
Progressor.Disable()
MusicButton.InteractedWithEvent.Subscribe(OnPressed)
OnPressed(Agent : agent) : void =
# Each press kicks the chord progression on.
Progressor.Enable()
Pattern 2 — Disable on round end
When the match ends, kill the adaptive music so the outro plays clean. This drives Disable from a Round Settings end event.
note_progressor_round_end := class(creative_device):
@editable
Progressor : note_progressor_device = note_progressor_device{}
@editable
EndZone : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
# Music is active during play...
Progressor.Enable()
EndZone.TriggeredEvent.Subscribe(OnRoundOver)
OnRoundOver(Agent : ?agent) : void =
# ...and goes quiet the moment the end zone fires.
Progressor.Disable()
Pattern 3 — Timed intro then enable
Let the calm intro breathe for a few seconds, then bring the harmony in automatically — no player input needed. Uses Sleep with Enable.
note_progressor_intro := class(creative_device):
@editable
Progressor : note_progressor_device = note_progressor_device{}
OnBegin<override>()<suspends> : void =
# Start flat.
Progressor.Disable()
# Hold the calm intro for 8 seconds.
Sleep(8.0)
# Then bring the chord progression in.
Progressor.Enable()
Gotchas
- No events of its own. The note_progressor_device exposes only
EnableandDisable— there is noNotePlayedEventor progression-step callback. If you need to react to musical timing, drive that from anote_trigger_deviceor your ownSleeploop; the progressor is purely a transposition stage you switch on and off. - You must bind the editable. A bare
note_progressor_device{}is an empty placeholder. CallingEnable()on an unbound field silently does nothing in play. Always set the field to the real placed device in the UEFN Details panel. - Subscribe in
OnBegin, handle at class scope. Event handlers likeOnStartSteppedare methods of the class, not nested functions. Subscribe to them insideOnBegin; defining aSubscribecall elsewhere will not run. - Unwrap
?agent.TriggeredEventdelivers a?agent. You can't use it directly — writeif (Player := Agent?):first. (Button'sInteractedWithEventinstead hands a plainagent, so no unwrap there — note the difference between the two patterns above.) Enable/Disableare idempotent and harmless to repeat. CallingEnable()on an already-enabled progressor is fine, so you don't need to track state with avar logicunless your own logic depends on it.- It's a music device, not an audio source. The progressor transposes notes but doesn't make sound on its own — it needs a downstream synthesizer/speaker in the Patchwork graph. Enabling it with nothing wired in produces silence even though the call succeeds.