Reference Verse compiles

Integer Division & Mod: Cycling a Timer Through Cove Waves

On a bright, cel-shaded cove, waves roll in on a rhythm — and rhythms are just counting with wrap-around. Verse's integer division and Mod operators turn a plain wave counter into repeating phases, and we wire those phases to a real timer_device and trigger_device so the island actually reacts.

Updated Examples verified on the live UEFN compiler

Overview

Integer math is the quiet workhorse behind almost every game system that repeats: every Nth wave, every 3rd chest, a phase that loops 0→1→2→0. Verse gives you two operators for this:

  • Integer division A / B — but note: in Verse the / operator on two ints produces a rational, not an int. To get a whole-number quotient you divide and floor, or you keep a running counter and use subtraction/Mod. The safe, always-int companion is Mod.
  • ModA Mod B gives the remainder after dividing A by B. 7 Mod 3 = 1. This is the single most useful operator for cycles: Counter Mod 3 walks 0,1,2,0,1,2… forever.

The game problem: imagine a pirate cove where a trigger_device fires once per incoming wave. You want every 4th wave to be a big one that starts a timer_device countdown (a warning before the tide floods the dock). That "every 4th" logic is exactly WaveCount Mod 4 = 0. Reach for integer division and Mod whenever gameplay repeats on a fixed interval.

API Reference

timer_device

Provides a way to keep track of the time something has taken, either for scoreboard purposes, or to trigger actions. It can be configured in several ways, either acting as a countdown to an event that is triggered at the end, or as a stopwatch for an action that needs to be completed before a set time runs out.

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

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

Events (subscribe a handler to react):

Event Signature Description
SuccessEvent SuccessEvent<public>:listenable(?agent) Signaled when the timer completes or ends with success. Sends the agent that activated the timer, if any.
FailureEvent FailureEvent<public>:listenable(?agent) Signaled when the timer completes or ends with failure. Sends the agent that activated the timer, if any.
StartUrgencyModeEvent StartUrgencyModeEvent<public>:listenable(?agent) Signaled when the timer enters Urgency Mode. Sends the agent that activated the timer, if any.

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>(Agent:agent):void Enables this device for Agent.
Enable Enable<public>():void Enables this device.
Disable Disable<public>(Agent:agent):void Disables this device for Agent. While disabled this device will not receive signals.
Disable Disable<public>():void Disables this device. While disabled this device will not receive signals.
ResetForAll ResetForAll<public>(Agent:agent):void Resets the timer back to its base time and stops it for all agents.
ResetForAll ResetForAll<public>():void Resets the timer back to its base time and stops it for all agents.
Start Start<public>(Agent:agent):void Starts the timer for Agent.
Start Start<public>():void Starts the timer.
Pause Pause<public>(Agent:agent):void Pauses the timer for Agent.
Pause Pause<public>():void Pauses the timer.
Resume Resume<public>(Agent:agent):void Resumes the timer for Agent.
Resume Resume<public>():void Resumes the timer.
Complete Complete<public>(Agent:agent):void Completes the timer for Agent.
Complete Complete<public>():void Completes the timer.
StartForAll StartForAll<public>(Agent:agent):void Starts the timer for all agents.
StartForAll StartForAll<public>():void Starts the timer for all agents.
PauseForAll PauseForAll<public>(Agent:agent):void Pauses the timer for all agents.
PauseForAll PauseForAll<public>():void Pauses the timer for all agents.
ResumeForAll ResumeForAll<public>(Agent:agent):void Resumes the timer for all agents.
ResumeForAll ResumeForAll<public>():void Resumes the timer for all agents.
CompleteForAll CompleteForAll<public>(Agent:agent):void Completes the timer for all agents.
CompleteForAll CompleteForAll<public>():void Completes the timer for all agents.
Save Save<public>(Agent:agent):void Saves this device's data for Agent.
Load Load<public>(Agent:agent):void Loads this device's saved data for Agent.
ClearPersistenceData ClearPersistenceData<public>(Agent:agent):void Clears this device's saved data for Agent.
ClearPersistenceDataForAll ClearPersistenceDataForAll<public>(Agent:agent):void Clears this device's saved data for all agents.
ClearPersistenceDataForAll ClearPersistenceDataForAll<public>():void Clears this device's saved data for all agents.
SetActiveDuration SetActiveDuration<public>(Time:float, Agent:agent):void Sets the remaining time (in seconds) on the timer, if active, on Agent.
SetActiveDuration SetActiveDuration<public>(Time:float):void Sets the remaining time (in seconds) on the timer, if active. Use this function if the timer is set to use the same time for all agent's.
GetActiveDuration GetActiveDuration<public>(Agent:agent)<transacts>:float Returns the remaining time (in seconds) on the timer for Agent.
GetActiveDuration GetActiveDuration<public>()<transacts>:float Returns the remaining time (in seconds) on the timer if it is set to be global.
SetLapTime SetLapTime<public>(Agent:agent):void Sets the lap time indicator for Agent.
SetLapTimeForAll SetLapTimeForAll<public>(Agent:agent):void Sets the lap time indicator for all agents.
SetLapTimeForAll SetLapTimeForAll<public>():void Sets the lap time indicator for all agents.
SetMaxDuration SetMaxDuration<public>(Time:float):void Sets the maximum duration of the timer (in seconds).
GetMaxDuration GetMaxDuration<public>()<transacts>:float Returns the maximum duration of the timer (in seconds).
IsStatePerAgent IsStatePerAgent<public>()<transacts><decides>:void Succeeds if this device is tracking timer state for each individual agent independently. Fails if state is being tracked globally for all agent's.

trigger_device

Used to relay events to other linked devices.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from trigger_base_device.

trigger_device<public> := class<concrete><final>(trigger_base_device):

Events (subscribe a handler to react):

Event Signature Description
TriggeredEvent TriggeredEvent<public>:listenable(?agent) Signaled when an agent triggers this device. Sends the agent that used this device. Returns false if no agent triggered the action (ex: it was triggered through code).

Methods (call these to make the device act):

Method Signature Description
Trigger Trigger<public>(Agent:agent):void Triggers this device with Agent being passed as the agent that triggered the action. Use an agent reference when this device is setup to require one (for instance, you want to trigger the device only with a particular agent.
Trigger Trigger<public>():void Triggers this device, causing it to activate its TriggeredEvent event.
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
SetMaxTriggerCount SetMaxTriggerCount<public>(MaxCount:int):void Sets the maximum amount of times this device can trigger. * 0 can be used to indicate no limit on trigger count. * MaxCount is clamped between [0,20].
GetMaxTriggerCount GetMaxTriggerCount<public>()<transacts>:int Gets the maximum amount of times this device can trigger. * 0 indicates no limit on trigger count.
GetTriggerCountRemaining GetTriggerCountRemaining<public>()<transacts>:int Returns the number of times that this device can still be triggered before hitting GetMaxTriggerCount. Returns 0 if GetMaxTriggerCount is unlimited.
SetResetDelay SetResetDelay<public>(Time:float):void Sets the time (in seconds) after triggering, before the device can be triggered again (if MaxTrigger count allows).
GetResetDelay GetResetDelay<public>()<transacts>:float Gets the time (in seconds) before the device can be triggered again (if MaxTrigger count allows).
SetTransmitDelay SetTransmitDelay<public>(Time:float):void Sets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered.
GetTransmitDelay GetTransmitDelay<public>()<transacts>:float Gets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered.

vector3

3-dimensional vector with float components.

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

vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:

Walkthrough

Here is the full cove scenario. A trigger fires each time a wave rolls in. We keep an int counter. Every 4th wave (Mod 4 = 0) we start a countdown timer; every 8th wave we complete/reset it as a "big set" ends. We also use integer division to compute which set number we're on (WaveCount / 4, floored) and set the timer's remaining duration from it.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Verse }

cove_waves := class(creative_device):

    # The plate/trigger a wave steps on each time it rolls in.
    @editable
    WaveTrigger : trigger_device = trigger_device{}

    # The countdown shown when a big wave set arrives.
    @editable
    FloodTimer : timer_device = timer_device{}

    # Running count of waves that have arrived this game.
    var WaveCount : int = 0

    OnBegin<override>()<suspends>:void =
        # React to every wave that triggers the plate.
        WaveTrigger.TriggeredEvent.Subscribe(OnWave)
        # If the timer succeeds (survived the countdown), reset it for reuse.
        FloodTimer.SuccessEvent.Subscribe(OnTimerDone)

    OnWave(Agent : ?agent) : void =
        # Advance the wave counter by one.
        set WaveCount = WaveCount + 1

        # Mod is the always-int cycle operator: 0 means "every 4th wave".
        # Mod is fallible (<decides>), so bind it in a failure context first.
        if (R := Mod[WaveCount, 4]):
            if (R = 0):
                # Integer set number: how many complete sets of 4 have passed.
                # We build a floored quotient by counting down with subtraction.
                SetNumber := FlooredDiv(WaveCount, 4)

                # Give bigger sets a longer warning: 5 seconds per set.
                Seconds := SetNumber * 5
                FloodTimer.SetActiveDuration(IntToFloat(Seconds))
                FloodTimer.StartForAll()

        # Every 8th wave closes out the big set early.
        if (R8 := Mod[WaveCount, 8]):
            if (R8 = 0):
                FloodTimer.CompleteForAll()

    OnTimerDone(Agent : ?agent) : void =
        # Countdown ended successfully — reset for the next big set.
        FloodTimer.ResetForAll()

    # Floored integer quotient built only from int-safe operations.
    FlooredDiv(A : int, B : int) : int =
        var Count : int = 0
        var Remaining : int = A
        loop:
            if (Remaining < B):
                break
            set Remaining = Remaining - B
            set Count = Count + 1
        Count

    # int -> float, since Verse does NOT auto-convert.
    IntToFloat(N : int) : float =
        1.0 * N```

**Line by line:**

- `@editable WaveTrigger`/`FloodTimer`  the two placed devices. You MUST declare them as fields; calling `trigger_device{}.Trigger()` on a bare literal does nothing on your map.
- `var WaveCount : int = 0`  our cycle counter. `var` because we mutate it.
- `WaveTrigger.TriggeredEvent.Subscribe(OnWave)`  every step on the plate calls `OnWave`. The event is `listenable(?agent)`, so the handler takes `(Agent : ?agent)`.
- `set WaveCount = WaveCount + 1`  advance the count.
- `WaveCount Mod 4 = 0`  the heart of it. `Mod` returns the remainder; when it's `0`, the count is an exact multiple of 4.
- `FlooredDiv(WaveCount, 4)`  a whole-number quotient. We avoid the `int/int  rational` pitfall by subtracting `B` repeatedly and counting.
- `SetNumber * 5`  int × int is fine and stays `int`.
- `FloodTimer.SetActiveDuration(IntToFloat(Seconds))`  `SetActiveDuration` wants a `float`, so we convert with `1.0 * N`.
- `FloodTimer.StartForAll()` / `CompleteForAll()` / `ResetForAll()`  real timer_device methods that make the countdown run, snap to finish, and rewind.

## Common patterns

**1. `Mod` to fire a trigger only every 3rd chest**  call `Trigger()` directly from code on the Nth event.

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

chest_bonus := class(creative_device):

    @editable
    ChestPlate : trigger_device = trigger_device{}

    @editable
    BonusTrigger : trigger_device = trigger_device{}

    var Opened : int = 0

    OnBegin<override>()<suspends>:void =
        ChestPlate.TriggeredEvent.Subscribe(OnChest)

    OnChest(Agent : ?agent) : void =
        set Opened = Opened + 1
        # Every 3rd chest fires the bonus device from code.
        if (Opened Mod 3 = 0):
            BonusTrigger.Trigger()

2. Integer division to scale trigger reset delay by tier. Fewer remaining triggers → shorter cooldown.

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

cannon_cooldown := class(creative_device):

    @editable
    Cannon : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        Cannon.SetMaxTriggerCount(6)
        Cannon.TriggeredEvent.Subscribe(OnFire)

    OnFire(Agent : ?agent) : void =
        Remaining := Cannon.GetTriggerCountRemaining()
        # Halve the remaining count with a floored quotient, use as seconds.
        Tier := FlooredDiv(Remaining, 2)
        Cannon.SetResetDelay(1.0 * Tier)

    FlooredDiv(A : int, B : int) : int =
        var Count : int = 0
        var Remaining : int = A
        loop:
            if (Remaining < B). { break }
            set Remaining = Remaining - B
            set Count = Count + 1
        Count

3. Mod to cycle a timer between short/long durations each wave.

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

tide_phases := class(creative_device):

    @editable
    Beat : trigger_device = trigger_device{}

    @editable
    PhaseTimer : timer_device = timer_device{}

    var Phase : int = 0

    OnBegin<override>()<suspends>:void =
        Beat.TriggeredEvent.Subscribe(OnBeat)

    OnBeat(Agent : ?agent) : void =
        set Phase = Phase + 1
        # 0,1,2 cycle: even phases = long tide, odd = short.
        if (Phase Mod 2 = 0):
            PhaseTimer.SetActiveDuration(10.0)
        else:
            PhaseTimer.SetActiveDuration(4.0)
        PhaseTimer.StartForAll()

Gotchas

  • int / int is NOT an int in Verse — it's a rational. If you write WaveCount / 4 expecting a whole number, you'll get a type mismatch when you try to use it where an int is required. Use Mod for cycles, and build a floored quotient with repeated subtraction (as in FlooredDiv) when you truly need an int quotient.
  • No implicit int→float. SetActiveDuration and SetResetDelay take float. Convert with 1.0 * N (or keep a float directly). Passing an int will not compile.
  • Mod sign with negatives. Mod follows the sign of the dividend, so -7 Mod 3 is not the same as 7 Mod 3. Keep counters non-negative (start at 0 and only add) so your cycle logic stays predictable.
  • ?agent must be unwrapped. The handler receives (Agent : ?agent). If you need the actual player, do if (A := Agent?): first. In the wave example we don't need the agent, so we use the ForAll timer methods instead of per-agent ones.
  • Bare device literals do nothing. timer_device{} written inline is a default value for an @editable field — it won't drive the timer you placed on the cove unless you assign the real device in the Details panel and call methods through the field.
  • Mod 0 errors. Never Mod by zero. If a divisor can be data-driven, guard it (if (B > 0):) before using it.

Guides & scripts that use timer_device

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

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