What you will build
Barnaby's Jungle Mod-Rally has two moments that live or die on randomness. First, the Sunrise Summit mod station rolls a mod tier — Rusty, Bronze, Silver, or Gold — the instant a racer arrives. Second, the Zipline Run gate rolls a banana-boost spawn chance, so sometimes a pickup appears and sometimes the jungle keeps its bananas. Predictable racing is boring racing; a little dice-rolling keeps every lap tense.
In this lesson you build exactly that piece: a mod_roll_gate device that listens for a racer passing the Zipline Run trigger, rolls GetRandomInt(0, 3) for the mod tier, and rolls GetRandomFloat(0.0, 1.0) against a tunable spawn chance to decide whether a banana boost appears. This is the randomness engine the full north-jungle-mod-rally capstone plugs straight into.
Barnaby's advice before we start: random numbers in Verse come from ONE module — /Verse.org/Random — and both bounds are inclusive. That second fact is the number-one gotcha in this whole lesson, so keep a paw on it.
Walkthrough
Step 1 — Import the Random module
GetRandomInt and GetRandomFloat live in /Verse.org/Random. Without that using line the compiler has never heard of them:
using { /Verse.org/Random }
Step 2 — Know your two dice
GetRandomInt(Low:int, High:int):int— returns a random int betweenLowandHigh, inclusive on both ends.GetRandomInt(0, 3)can return0,1,2, or3— that is FOUR possible values, not three. If you are used to other languages where the upper bound is exclusive, this is the trap.GetRandomFloat(Low:float, High:float):float— returns a random float betweenLowandHigh, inclusive.GetRandomFloat(0.0, 1.0)is the classic percentage roll: compare it against a threshold like0.35for a 35% chance.
Step 3 — The complete mod-roll gate
Place a trigger_device across the Zipline Run gate and an item_spawner_device (loaded with your banana-boost item) beside the track, then wire both into this device in the editor:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Zipline Run mod gate: rolls a mod tier and a banana-boost spawn chance
# every time a racer rides through the trigger.
mod_roll_gate := class(creative_device):
# The trigger racers pass through at the Zipline Run gate.
@editable
ZiplineGate : trigger_device = trigger_device{}
# Spawns one banana-boost pickup when the chance roll succeeds.
@editable
BananaSpawner : item_spawner_device = item_spawner_device{}
# 0.0 = never, 1.0 = always. Tune it in the editor — no code changes.
@editable
BananaChance : float = 0.35
# Index matches the tier number rolled below: 0..3.
TierNames : []string = array{"Rusty", "Bronze", "Silver", "Gold"}
OnBegin<override>()<suspends>:void =
ZiplineGate.TriggeredEvent.Subscribe(OnGatePassed)
OnGatePassed(MaybeAgent : ?agent) : void =
# Roll the mod tier. GetRandomInt is INCLUSIVE on BOTH ends,
# so (0, 3) produces 0, 1, 2, or 3 — four possible tiers.
Tier := GetRandomInt(0, 3)
if (Name := TierNames[Tier]):
Print("Mod box roll: {Name} (tier {Tier})")
# Roll the banana-boost chance: a float in [0.0, 1.0].
Roll := GetRandomFloat(0.0, 1.0)
if (Roll < BananaChance):
BananaSpawner.SpawnItem()
Print("Banana boost spawned! Rolled {Roll}")
else:
Print("No banana this time. Rolled {Roll}")
What each piece is doing
using { /Verse.org/Random }— bringsGetRandomIntandGetRandomFloatinto scope. Forget it and neither function exists.BananaChance : float = 0.35with@editable— the spawn chance is data, not code. Your designer (or future you) drags the slider in the editor to make the jungle more or less generous. No recompiles for balance passes.Tier := GetRandomInt(0, 3)— one roll, four outcomes. Because both bounds are inclusive, the tier count isHigh - Low + 1, notHigh - Low.if (Name := TierNames[Tier]):— array indexing in Verse is a failable expression, so it lives inside anif. SinceTieris always 0..3 and the array has exactly four entries, this always succeeds — but the compiler still insists you handle the failure case, and that discipline saves you the day someone shortens the array.if (Roll < BananaChance):— the comparison is the whole spawn-chance mechanic. A roll of0.12beats a0.35threshold and a banana appears; a roll of0.80does not.BananaSpawner.SpawnItem()— the realitem_spawner_deviceAPI call that actually drops the pickup on the track.
Common patterns
Weighted loot tiers with float thresholds
Equal odds for Gold and Rusty feels wrong — Gold should be rare. Slice the 0.0..1.0 range unevenly and check thresholds in ascending order:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /UnrealEngine.com/Temporary/Diagnostics }
# One roll, uneven slices: 60% common, 30% rare, 10% legendary.
loot_tier_demo := class(creative_device):
OnBegin<override>()<suspends>:void =
Roll := GetRandomFloat(0.0, 1.0)
if (Roll < 0.6):
Print("Common mod — the 0.0..0.6 slice, 60% of rolls")
else if (Roll < 0.9):
Print("Rare mod — the 0.6..0.9 slice, 30% of rolls")
else:
Print("LEGENDARY mod — the top 10%. Barnaby is impressed.")
Shuffle an array for a random pick
/Verse.org/Random also ships Shuffle, which returns a NEW array with the same elements in random order (the original is untouched). Shuffling and taking element [0] is the cleanest way to pick one random entry:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Random }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Pick today's surprise bonus checkpoint from the rally route.
bonus_stop_demo := class(creative_device):
Checkpoints : []string = array{"Clifftop Lookout", "Rope-Bridge Canyon", "Zipline Run", "Waterfall Pool"}
OnBegin<override>()<suspends>:void =
Shuffled := Shuffle(Checkpoints)
if (BonusStop := Shuffled[0]):
Print("Today's bonus checkpoint: {BonusStop}")
Where this goes next
This is capstone piece #15 of Barnaby's Jungle Mod-Rally (north-jungle-mod-rally). The full rally imports this randomness engine directly:
- The Sunrise Summit mod station uses the
GetRandomInt(0, 3)tier roll to decide which mod tier thevehicle_mod_box_spawner_deviceawards. - The Zipline Run gate uses the
GetRandomFloatchance roll exactly as built here, feeding theitem_spawner_devicebanana-boost pickups from lesson 29 (item-spawner-device). - Lesson 17 (
verse-classes-and-structs) wraps the tier number in a propermod_rewardstruct, and lesson 30 (item-granter-device) grants the rolled reward to the racer.
One roll for the tier, one roll for the banana — and suddenly no two laps of Codewood Grove ever play the same.