npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rbxts/weather

v0.1.0

Published

Rain, snow, fog and storms for roblox-ts: one call to change the weather, zones for local weather, shelter under roofs

Readme

@rbxts/weather

Weather for roblox-ts: rain, snow, fog and storms in one call.

Weather.rain();
Weather.snow({ intensity: 0.4, transition: 20 });
Weather.zone(marshPart).fog();
  • One call per weather. Nine presets, every field adjustable, smooth transitions between any two.
  • Server-driven, no remotes. Set the weather on the server and every client follows. A player who joins mid-transition picks it up where it is. Lightning flashes at the same moment for everyone.
  • Local weather. Zones give a region weather of its own (fog in the marsh, snow on the peak), fading into the surrounding weather at the edge.
  • Shelter. Rain stops on roofs instead of falling through them, nothing falls in caves, and sounds are muffled indoors.
  • No assets to upload, no dependencies. Rain and snow use textures that ship with every Roblox client, the default sounds come from Roblox's public audio library, and the autumn leaves are the package's own images, already on Roblox.

Install

npm install @rbxts/weather

Quick start

On the server, set the weather:

import { Weather } from "@rbxts/weather";

Weather.rain({ transition: 10 });
task.wait(120);
Weather.storm();

On every client, start drawing it once:

import { Weather } from "@rbxts/weather";

Weather.start();

Presets

| Call | Looks like | intensity sets | | -------------------- | -------------------------------------------- | ---------------- | | Weather.clear() | A few white clouds, light breeze | - | | Weather.cloudy() | Broken cloud | clouds | | Weather.overcast() | Grey sky, slightly dim | clouds | | Weather.fog() | Thick fog | fog | | Weather.drizzle() | Light rain, grey sky | rain | | Weather.rain() | Steady rain, dark clouds | rain | | Weather.storm() | Heavy rain, strong wind, lightning | rain | | Weather.snow() | Falling snow, white haze | snow | | Weather.blizzard() | Driving snow, strong wind, little visibility | snow |

Each takes the same options:

Weather.rain({
	intensity: 0.4, // the preset's main amount, 0-1
	transition: 15, // seconds to blend in (default 5, 0 = at once)
	wind: new Vector3(20, 0, 0), // and any weather field below
});

Weather.set takes a preset name, or some fields to change on the current weather:

Weather.set("storm", { transition: 30 });
Weather.set({ fog: 0.6 }); // everything else stays

Weather fields

| Field | Range | Drives | | -------------- | ---------------- | ------------------------------------------------------- | | rain | 0-1 | Rain particles, splashes, rain sound | | snow | 0-1 | Snow particles | | clouds | 0-1 | Clouds.Cover | | cloudDensity | 0-1 | Clouds.Density | | cloudColor | Color3 | Clouds.Color | | fog | 0-1 | Atmosphere density, haze and colour | | fogColor | Color3 | The colour fog tints towards | | darkness | 0-1 | A colour grade that darkens and desaturates the scene | | wind | Vector3, studs/s | Tilts rain and snow, Workspace.GlobalWind, wind sound | | lightning | 0-1 | How often lightning flashes |

Weather.get() is the weather right now (partway through a transition), Weather.getTarget() where it is heading. PRESETS holds the presets' values and lerpParams blends two weathers.

Seasons

The season is separate from the weather: picking a preset keeps it, and zones do not have one.

Weather.setSeason("autumn", { intensity: 0.7, transition: 30 });
Weather.rain({ season: "autumn" }); // also accepted alongside any weather call
Weather.set({ season: "winter", seasonIntensity: 0.5 });
Weather.getSeason(); // { season: "autumn", intensity: 0.7 }

| Season | Drawn | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | autumn | Leaves blow through the view near the ground, tumbling with the wind, then settle and fade. Each starts out of sight and blows in. More in a strong wind; intensity sets how many. | | spring, summer, winter | Nothing yet: available to read for gameplay. |

seasonIntensity (0-1, default 1) is how strongly the season shows. Changing season fades the old one out, then the new one in. The default is summer. Like the weather, it is set on the server for everyone, or on a client for that player (reset() drops it too), and Weather.sample() includes season and seasonIntensity.

Zones

A zone gives a region its own weather. Inside it, its weather replaces the global one; outside, it fades out over blend studs.

const marsh = Weather.zone(workspace.Marsh, { blend: 30 }).fog();
const peak = Weather.zone({ position: new Vector3(0, 400, 0), radius: 150 }).blizzard();
const valley = Weather.zone({ cframe: valleyCFrame, size: new Vector3(300, 200, 300) }).clear();
  • A region is a part (its box; followed while it moves), a { cframe, size } box or a { position, radius } sphere. The part does not have to replicate or stream in, and while it is invisible (or CanQuery is off) it does not stop rain.
  • A zone has no effect until its weather is set. Change it like the global weather: marsh.rain({ transition: 10 }).
  • Where zones overlap, higher priority wins; equal priorities apply in the order they were made.
  • setRegion, setBlend, setPriority and destroy change it later.

Server and client

Called on the server, everything changes the weather for all players.

Called on a client, it changes the weather for that player only, over the server's: a cutscene, an indoor dream, a per-player setting. Weather.reset() hands the player back to the server's weather. Client zones work the same way.

Any client-side call starts drawing; otherwise call Weather.start().

Gameplay

Weather.sample(position) is the weather at a point right now, zones included, on either side. Use it for rules that depend on the weather: crops watered by rain, fires that will not light, cold in a blizzard.

if (Weather.sample(field.Position).rain > 0.3) waterCrops(field);

On a client, Weather.sample() with no position is what is being drawn at the camera, and Weather.getExposure() is how exposed the camera is to the sky: 0 under a roof, 1 in the open.

How it is drawn (client)

  • Rain and snow fall from a grid of columns that follows the camera: 5 x 5 (80 studs across) for rain, 13 x 13 (208 studs) for slow-falling snow, so you cannot walk out of it. Each column finds the first thing below it and gives its particles just enough life to reach it: rain lands on roofs and treetops, not inside houses. A column with something above it (a cave, an overhang) stays dry. Parts that are almost invisible are ignored, as are player characters.
  • Splashes on the ground near the camera while it rains.
  • Sky. Fog is laid over the game's own Atmosphere (or one the package adds), clouds are set on Terrain.Clouds (added if missing), and a ColorCorrectionEffect darkens the scene. Lighting.Brightness and ClockTime are left alone, so a day/night cycle keeps working.
  • Wind sets Workspace.GlobalWind, which sways terrain grass and moves clouds.
  • Screen drops (opt in with screenDrops: true): water lands on the lens while the camera is out in the rain, most when looking up or into the wind, none under a roof. The drops are small glass balls just in front of the camera, so they refract the scene behind them, blurred out of focus by a DepthOfFieldEffect that only reaches the first stud. Some run down the screen; all fade. The blur is only enabled while drops are showing. Refraction needs a graphics quality that renders glass; on low settings the drops are plain translucent blobs.
  • Storm clouds: Roblox's own clouds turn into a flat sheet when the sky is fully covered, so dark, cloudy weather adds two drifting layers of real storm-cloud texture overhead (the lower one faster, for depth). They fade in with the weather: faint when overcast, solid in rain, a heavy sky in a storm, lit from within by lightning. Under them the fog is kept thin enough to see them. Turn off with stormClouds: false; appearance.cloudTexture swaps the texture.
  • Lightning flashes the colour grade; thunder follows a moment later if you gave it a sound.

Weather.stop() puts everything back as it was.

Configuration

Weather.configure({
	sky: true, // drive Clouds, Atmosphere and the colour grade
	wind: true, // drive Workspace.GlobalWind
	particles: 1, // rate multiplier (default 0.5 on touch devices)
	shelter: true, // stop rain at roofs, keep caves dry
	screenDrops: false, // water drops on the screen in the rain
	stormClouds: true, // storm cloud layers overhead in dark weather (needs sky)
	focus: () => character.GetPivot().Position, // where weather is drawn around (default: camera)
	ignore: [workspace.Effects], // more instances that do not stop rain
	sounds: {
		rain: "rbxassetid://...",
		wind: "rbxassetid://...",
		thunder: ["rbxassetid://...", "rbxassetid://..."], // one is picked per strike
		volume: 0.5,
	},
	appearance: {
		rainTexture: "rbxassetid://...", // a streak texture; then set rainSquash to 0
		rainColor: Color3.fromRGB(190, 200, 215),
		rainSize: 0.15,
		rainSquash: -3, // negative stretches drops into streaks
		rainTransparency: 0.85,
		snowTexture: "rbxassetid://...",
		snowColor: Color3.fromRGB(255, 255, 255),
		snowSize: 0.22,
		splashColor: Color3.fromRGB(205, 215, 228),
		leaves: [{ texture: "rbxassetid://...", size: 1, tint: Color3.fromRGB(255, 230, 200) }], // replaces the default leaves
		cloudTexture: "rbxassetid://...", // the storm cloud layers: tileable, seen from below
		leafSize: 1, // studs, before each picture's own size
		leafMeshes: ["rbxassetid://..."], // curved cards the pictures are drawn on, one picked per leaf
	},
});

Turn sky off if your game manages its own Atmosphere and Clouds and only wants precipitation, wind and sound from the package. Read the weather with Weather.sample() and drive your sky from it.

Sounds default to recordings from Roblox's public audio library, free for every experience: a heavy rain loop and four thunder strikes from Pro Sound Effects, and a howling wind from DistroKid's official account. Pass your own ids to replace them (thunder takes one id or a list to pick from at random), or "" to turn one off. Each strike is pitched a little differently.

Licence

ISC