Log inGet started
·
scene · drop-in viewer
asset⌬ scenesceneprimary: entrypoint.luau·originates fromworld 0fc7535e-6…

fx_storm

A thunderstorm around a lone stone tower: the `storm` Generator (the `storm.storm` graph) on the `storm` entity at (-100, 0, 220) draws the rain, splashes, rain sheets, lightning bolts, sparks and smoke; the `tower` entity stands the `storm.tower` keep. The `StormDirector` compon…

byzero-proxy @ DESKTOP-DB3UJOJ·posted 11d ago
What it does

fx_storm

A thunderstorm around a lone stone tower: the storm Generator (the storm.storm graph) on the storm entity at (-100, 0, 220) draws the rain, splashes, rain sheets, lightning bolts, sparks and smoke; the tower entity stands the storm.tower keep. The StormDirector component beside the Generator plays the thunder (Thunder1 to Thunder3) and lights each strike with the FlashKey and FlashFill lights, and over the main scene it swings the main scene's sun and dims its ambient light with the storm. StormRain carries the rain sound, heard within 70 m of the tower, and the thunder carries 300 m.

Loaded as an overlay by the main scene, under the main scene's sky. Loaded on its own, its sky is the storm deck (storm_sky, lit by each strike) and it spawns a player 35 m from the tower, facing it.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

fx_storm: a thunderstorm with lightning striking a lone tower. Its effects run from the components in scene.json as the scene loads, on their own clocks, whether it loads on its own or as an overlay on the main scene. Loaded on its own, its sky is the storm deck (`storm_sky`), which StormDirector lights with each strike; as an overlay, the main scene's sky stands.

Skybox

stormSky( ) → void

The storm deck, while this scene is the root: a temporary entity, so it is never saved into the scene and goes when the scene does.

onLoad( ) → void

onEditLoad( ) → void

⌬ Metadata
descriptionA thunderstorm around a lone stone tower: rain, splashes, rain sheets, lightning strikes, thunder arriving at the speed of sound and lit clouds.

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

46+items
·
soundclip · born here
❒asset
# storm_thunder_3 Thunder sound clip for the lightning storm in the `fx_storm` scene. The scene's `Thunder3` entity references it from an Audio component with autoplay off, looping off, the `sfx` channel, source type `SoundEffect`, volume 1 and spatial off. `StormDirector` plays it. The storm loops every 13.6 s through four strikes (`storm/schedule.module`), and the director gives strike i the Audio component of the entity `Thunder` ((i - 1) mod 3) + 1. During play, when the storm clock passes a strike's time plus the distance from the strike's target to the hero camera divided by 343 m/s, it stops and restarts the clip with volume `thunderVolume` (1 in the scene) times 1.0 for a tower strike or 0.85 for a ground strike, and pitch `0.92 + 0.16 * ((i * 37) mod 11) / 10`. This clip sounds for strike 3, a ground strike at 8.6 s (pitch 0.936). `storm/audio.module` generates the samples in Luau and creates the clip with `asset.create` (mono, 32000 Hz); its `M.bake()` makes each storm clip whose name is still free. This clip comes from `M.thunder(151, 12)`: seed 151, 12 seconds, ending in a 0.6 s fade. `data.zaud` is the engine-native payload the runtime decodes and plays. Its header states Opus, 48000 Hz, 1 channel and 576000 frames, 12.0 seconds. `settings.yaml` sets the encoding: codec `opus`, 96 kbps, VBR on, `forceMono` false, load type `auto`.
▲ 0↑ born
◇
component · born here
❒asset
# StormDirector StormDirector handles everything about a lightning strike apart from the particles. The storm graph (the Generator on the same entity) owns the bolts, rain, splashes, sparks and smoke, and runs on one looping clock. StormDirector reads that same clock every frame and, through the shared `storm.schedule`, pours each strike's light over the rest of the scene: the sun swings to the bolt and throws the tower's shadow, point lights blaze at the strike, the cloud deck and the puddles light up, and the thunder follows at the speed of sound. Between strikes the values hold still, so its resting cost is one clock read. The fx_storm scene uses it on the `storm` entity, next to the Generator that plays the `storm.storm` graph, with `moonIntensity = 0.3` and `ambientIntensity = 0.05`. It requires `storm.schedule`. It runs at `executionOrder = 60`. It finds these by name, and finds them again every 2 seconds, whenever one of their entities is gone, and while it is still looking for the generator: | Name | What it reads | |------|---------------| | `sun` | Light: the moonlight that swings toward each bolt | | `ambient` | Light: the ambient level | | `FlashKey` | Light: the point light that blazes at the strike | | `FlashFill` | Light: the fill light high in the cloud | | `storm` | Generator: the storm clock | | `Thunder1`, `Thunder2`, `Thunder3` | Audio: the thunder sounds | | `storm_sky`, `storm_ground` | materials, resolved once as assets | ## Fields | Field | Type | Default | Description | |-------|------|---------|-------------| | `flashGain` | number | 1.0 | Scene-wide brightness of a strike's light, as a multiplier on the tuned defaults. | | `moonIntensity` | number | 1.7 | Moonlight before any strike: the sun light's intensity between strikes. | | `ambientIntensity` | number | 0.26 | The ambient light's intensity between strikes. | | `thunderVolume` | number | 1.0 | Thunder loudness. | All fields are `Sync`. ## What each frame does 1. Reads the generator's time and turns it into the storm phase with `schedule.phase`. 2. Sums every strike's weighted `envelope` into `flash` (held at most 3, then scaled by `flashGain`) and its weighted `afterglow` into `glow` (held at most 1.2). The strike with the largest `envelope + afterglow` leads the lighting. 3. Carries each strike's `target` and `top` from the graph's own space into the world through the `storm` entity's position and rotation (`Transform.localToWorld`). 4. In play (`update`), cues the thunder. Each strike's thunder plays when the phase passes the strike time plus the distance from the camera drawing the viewport to the point halfway up the strike, divided by 343. The strikes take turns over `Thunder1` to `Thunder3`; the volume is `thunderVolume` (times 0.85 for a ground strike) and each strike gets its own pitch near 1. 5. When `flash`, `glow` or the leading strike has moved since the last write, it updates: - the sun's direction, lerped from the moonlight direction toward the bolt's direction as the flash burns, its intensity (`moonIntensity + flash * 7 + glow * 0.6`) and its colour, from `{ 0.36, 0.46, 0.78 }` toward `{ 0.72, 0.80, 1.0 }`; - the ambient light's intensity (`ambientIntensity + flash * 0.55 + glow * 0.08`); - `FlashKey`, moved near the leading strike, at intensity `flash * 9000 + glow * 700`, and `FlashFill` at `flash * 7000 + glow * 500`; - `storm_sky`'s `flash` and `bolt_dir` (the direction from the camera drawing the viewport toward the bolt's top), and `storm_ground`'s `flash` and `bolt_pos` (the strike target). ## Lifecycle - `update(dt)`: runs the frame above with thunder cues. - `editorUpdate(dt)`: runs the same frame, skipping the thunder cues. Both use `dt` when given and 0.016 otherwise.
▲ 0↑ born
·
soundclip · born here
❒asset
# storm_rain Looping rain sound for the lightning storm in the `fx_storm` scene. The scene's `StormRain` entity plays it from an Audio component with autoplay on, looping on, the `sfx` channel, source type `Ambience`, volume 0.5 and spatial off. `storm/audio.module` generates the samples in Luau and creates the clip with `asset.create` (mono, 32000 Hz); its `M.bake()` makes each storm clip whose name is still free. This clip comes from `M.rainBed(7, 8.0)`, which generates 0.8 s more than the clip's 8 s and crossfades that tail into the start, so the end meets the beginning when it loops. `data.zaud` is the engine-native payload the runtime decodes and plays. Its header states PCM, 32000 Hz, 1 channel and 256000 frames, 8.0 seconds. `settings.yaml` sets codec `pcm`, `forceMono` false, load type `auto`.
▲ 0↑ born
◐
material · born here
❒asset
# storm_ground Ground material for the lightning storm scene `fx_storm`. The scene's `ground` entity (a built-in cube scaled 90 x 0.2 x 90 at (-100, -0.1, 220)) wears it. The `StormDirector` component on the `storm` entity resolves it by name and, on each frame where the strike light changes, writes `flash` and `bolt_pos` for the strongest current strike. Shader: `storm_ground` (`storm/shaders/storm_ground.shader`). Its README: sodden ground, with churned earth, rock, puddles with animated rain rings, and the lightning bolt's reflection in the pools. From its header: world-space and texture-free; puddles fill the hollows of a procedural height field and mirror the sky, rain rings spread on every wet patch, the strike's reflection is traced from the reflected view ray to the bolt's column, and a distance haze matched to the sky's horizon blends the far ground away. Render state: the defaults (opaque blend, back faces culled, depth write on). ## Properties mat.yaml sets `center_x` and `center_z`, every other property takes the shader default, and the director writes two of them at runtime: - `wet` 0.95: darkens the albedo, lowers roughness and fills more of the hollows with water. - `puddles` 1.0: multiplier on puddle coverage. - `flash` 0.0 (range 0 to 20): strike brightness, written by `StormDirector`; it scales the bolt's reflection in the pools and brightens the distance haze. - `bolt_pos` (0, 0, 0, 0): position of the strike's target, written by `StormDirector`; the shader uses its x and z as the bolt's column. - `fog` 0.011: density of the distance haze, applied as `1 - exp(-distance * fog)`. - `center_x` -100, `center_z` 220: where the keep stands; the ground within 9 units of it stays a drier apron and the puddles fill in from 9 to 16 units out.
▲ 0↑ born
·
soundclip · born here
❒asset
# storm_thunder_1 Thunder sound clip for the lightning storm in the `fx_storm` scene. The scene's `Thunder1` entity references it from an Audio component with autoplay off, looping off, the `sfx` channel, source type `SoundEffect`, volume 1 and spatial off. `StormDirector` plays it. The storm loops every 13.6 s through four strikes (`storm/schedule.module`), and the director gives strike i the Audio component of the entity `Thunder` ((i - 1) mod 3) + 1. During play, when the storm clock passes a strike's time plus the distance from the strike's target to the hero camera divided by 343 m/s, it stops and restarts the clip with volume `thunderVolume` (1 in the scene) times 1.0 for a tower strike or 0.85 for a ground strike, and pitch `0.92 + 0.16 * ((i * 37) mod 11) / 10`. This clip sounds for strike 1, a ground strike at 1.6 s (pitch 0.984), and strike 4, a tower strike at 11.0 s (pitch 1.0). `storm/audio.module` generates the samples in Luau and creates the clip with `asset.create` (mono, 32000 Hz); its `M.bake()` makes each storm clip whose name is still free. This clip comes from `M.thunder(117, 10)`: seed 117, 10 seconds, ending in a 0.6 s fade. `data.zaud` is the engine-native payload the runtime decodes and plays. Its header states Opus, 48000 Hz, 1 channel and 480000 frames, 10.0 seconds. `settings.yaml` sets the encoding: codec `opus`, 96 kbps, VBR on, `forceMono` false, load type `auto`.
▲ 0↑ born
·
procgraph · born here
❒asset
# storm A thunderstorm around a lone tower: rain driven slantwise by the wind that splashes off the ground and the tower, lightning bolts striking on the schedule `schedule.module` beside it keeps, sparks and smoke where each strike lands, and sheets of rain sweeping through. It is simulated on the GPU in one solver family. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("storm", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load", ending = "loop" }) ``` | Output | What it draws | |---|---| | `rain` | The falling rain, `storm_streak` shader | | `splash` | Splashes where rain lands, `storm_streak` shader | | `sheets` | Sheets of rain sweeping through, `storm_sheet` shader | | `bolt1` to `bolt4` | The lightning bolts, `lightning_bolt` shader | | `sparks` | Sparks where strikes land, `storm_streak` shader | | `smoke` | Smoke rising where strikes land, `storm_puff` shader | The timeline has no end and plays at 60 fps. In the Procgen Effects Showcase world's `fx_storm` scene, the `StormDirector` component on the same entity reads this clock and, on the same schedule, swings the sun to each bolt, blazes point lights at the strike, lights the cloud deck and the puddles, shakes the camera and plays the thunder.
▲ 0↑ born
·
soundclip · born here
❒asset
# storm_thunder_2 Thunder sound clip for the lightning storm in the `fx_storm` scene. The scene's `Thunder2` entity references it from an Audio component with autoplay off, looping off, the `sfx` channel, source type `SoundEffect`, volume 1 and spatial off. `StormDirector` plays it. The storm loops every 13.6 s through four strikes (`storm/schedule.module`), and the director gives strike i the Audio component of the entity `Thunder` ((i - 1) mod 3) + 1. During play, when the storm clock passes a strike's time plus the distance from the strike's target to the hero camera divided by 343 m/s, it stops and restarts the clip with volume `thunderVolume` (1 in the scene) times 1.0 for a tower strike or 0.85 for a ground strike, and pitch `0.92 + 0.16 * ((i * 37) mod 11) / 10`. This clip sounds for strike 2, a tower strike at 5.0 s (pitch 1.048). `storm/audio.module` generates the samples in Luau and creates the clip with `asset.create` (mono, 32000 Hz); its `M.bake()` makes each storm clip whose name is still free. This clip comes from `M.thunder(134, 11)`: seed 134, 11 seconds, ending in a 0.6 s fade. `data.zaud` is the engine-native payload the runtime decodes and plays. Its header states Opus, 48000 Hz, 1 channel and 528000 frames, 11.0 seconds. `settings.yaml` sets the encoding: codec `opus`, 96 kbps, VBR on, `forceMono` false, load type `auto`.
▲ 0↑ born
·
procgraph · born here
❒asset
# tower A lone stone keep: a plinth, a square shaft, a corbelled gallery with a crenellated parapet, a round turret under a conical roof and an iron finial, 48.6 m to the tip of the finial. It is built from boxes, cylinders, a cone and a sphere joined into one entity output: the stone draws with the `storm_stone` shader and the finial with dark metal. ```lua -- `graph` is this graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("tower", { position = { 0, 0, 0 } }) e.component.add("Generator", { graph = graph }) ``` The output `keep` is the tower. It stands at the centre of the Procgen Effects Showcase world's `fx_storm` scene.
▲ 0↑ born
❒
package · born here
❒asset
# effectShowcase The procedural effects of the Procgen Effects Showcase world. Each one is a `.procGraph` that plays through a `Generator`, and every shader, material and module a graph draws with sits beside it in this package, so the package carries everything its graphs need. Each graph's README says what it makes, how to place it and what each of its inputs changes. ## Contents | Folder | Graphs | What they make | |---|---|---| | `combat/` | `impact`, `muzzleFlash`, `tracer` | A round striking a hard surface, the bloom at a barrel as a weapon fires, and the glowing streak of a round in flight. They draw with `fxFlash`, `fxSmoke` and `fxSpark` in `combat/shaders/`. | | `blast/` | `wall_blast` | A charge blowing a breach through a stone block wall, on a 9.6 s loop. | | `storm/` | `storm`, `tower` | A thunderstorm around a lone tower: wind-driven rain, lightning striking on the schedule `schedule.module` keeps, and sparks and smoke where strikes land. `tower` is the stone keep it stands around. | | `rift/` | `arcane_rift` | A rift tearing open in the ground, its motes and rubble moved by the compute shaders in `rift/compute/`. | | `dragon/` | `dragon_breath` | A dragon's fire breath sweeping a courtyard: a flame jet, rolling smoke and drifting embers. | | `launch/` | `launch` | A heavy-lift rocket liftoff on one looping timeline, with the heat-haze material `rk_haze_mat`. | | `waterfall/` | `wf_env`, `wf_water`, `wf_spray`, `wf_foam`, `wf_mist` | A waterfall built in parts: the cliff, basin and boulders, the falling and still water, the droplets, the foam where the falls land, and the mist with its rainbow. Its water materials are in `waterfall/materials/`. | | `shaders/` | | `fx_noise`, the noise functions the waterfall and wall blast shaders include. | ## Playing one A graph plays on a `Generator` component bound to it: ```lua -- `graph` is the graph's reference: the AssetRef `asset.resolve` or a search returns for it. local e = entity.spawn("impact", { position = { 0, 1, 0 } }) e.component.add("Generator", { graph = graph, playOn = "load" }) ``` Set a graph's inputs with the Generator's `params`, e.g. `params = { size = 3 }`.
▲ 0↑ born
backing path · scenes/fx_storm.scene

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.