It might still have a few rough edges - feel free to report any issues you find
Features
- Periodic rain cycles with configurable wet and dry durations
- Rain on multiple planets/surfaces, including Nauvis, Vulcanus, Fulgora, and modded planets (configurable)
- Rain can extinguish fires, with a configurable chance for each fire
- Pollution reduction during rain. Looks great with Pollution: Impactful Smog / Spore Cloud
- Reduced solar panel efficiency during rain (disabled by default)
- Lightning and thunder effects
- Configurable rain intensity
- Multiplayer support
- Commands to check the current weather or start a rain or dry period:
/dynamic-rain status
/dynamic-rain rain
/dynamic-rain dry
/dynamic-rain lightning 0 0

Lightning strikes
Rare Fulgora-style lightning, but unlike on Fulgora, these strikes can instantly kill living creatures and ignite flammable structures, while leaving other structures undamaged. (Space Age only)
- Can kill players unless they are inside a vehicle
- Can kill enemies, spawners, drones, and fish
- Can ignite trees, fuel pipes (works best with Flammable Oils), wooden chests, and small wooden electric poles
- Electric poles take no damage but may temporarily stop conducting power
- Radars are temporarily disabled when struck
- Chain discharges are also dangerous
- Flying with Jetpack during a thunderstorm is extremely dangerous
Remote API
start_phase(...)
- Temporarily overrides the weather on the specified surface.
- If the requested phase is already active, resets its timer to
duration_ticks. Otherwise, takes 600 ticks to fade rain in or out before starting the requested phase. - After the duration ends, Dynamic Rain continues its own scheduler.
- Each call replaces all options. Omitted options use player settings.
- API-enabled surfaces remain enabled after the episode ends.
remote.call("dynamic-rain", "start_phase",
surface_index, -- Existing surface index
"wet", -- "wet" or "dry"
20000, -- Duration: positive integer, ticks
{ -- Optional; omitted fields use player settings
intensity = 1, -- Absolute drop density: number >= 0 && < 100
thunderstorm = false, -- true / false; false disables thunder and lightning
fire_extinguish_chance = 0.7, -- 0..1; 0 disables extinguishing
pollution_cleanup_per_minute = 10, -- Number >= 0; 0 disables cleanup
pollution_max_chunks_per_tick = 10 -- Positive integer
}
)
To keep the surface dry until your next rain episode, call start_phase with "dry" and a suitable duration.
is_raining(...)
Returns true during the wet phase; false during dry weather or when rain is disabled.
local raining = remote.call("dynamic-rain", "is_raining", surface_index)
time_left(...)
Returns ticks remaining until the phase changes; 0 when rain is disabled.
local ticks_left = remote.call("dynamic-rain", "time_left", surface_index)
Events
local events = remote.call("dynamic-rain", "get_events")
script.on_event(events.on_phase_changed, function(event)
-- Raised when the phase actually changes
-- event.surface_index
-- event.old_phase, event.phase: "wet" / "dry"
-- event.duration_ticks: duration of the new phase
end)
script.on_event(events.on_rain_pollution_cleaned, function(event)
-- Raised when rain removes pollution
-- event.surface_index
for _, chunk in ipairs(event.chunks) do
-- chunk.chunk_position: { x, y }, chunk coordinates
-- chunk.pollution_before: pollution before cleanup
-- chunk.pollution_removed: amount removed
-- chunk.pollution_after: pollution remaining
end
end)