Environment

Usage guide of the environment kits: world.lighting, world.daynight, world.weather, world.atmosphere, world.water, world.fluids, world.biomes, world.grass and world.bindings: the map, settings and defaults, services, hooks, modding, engines.

Source: module-kits:kits/world_lighting/usage/en.mdView Markdown source

Also read offline — CLI: grip-forge docs world-environmentMCP tool: gripforge_docs { "topic": "world-environment" }

Environment of your world (world.* kits) #

The light, the time of day, the weather, the water, the regions and the grass of a game, each in its own kit. Readable offline: gripforge docs world-environment, or the MCP tool gripforge_docs (topic world-environment). The large landscape itself is the subject of world-terrain.

The map #

KitWhat it gives the game
world.lightingthe sun, the sky, the lamps, fog and haze, bloom, ambient occlusion, grading, named looks
world.daynighta clock (hours, days, dawn / day / dusk / night) and a sun that follows it
world.weathersnow, blizzard, rain, storm, fog; snow cover, wet ground, traction, visibility, cold
world.atmospherethe look of the world follows a number of the game (sky, sun, grass, weather)
world.waterrivers, lakes, lava and ice with a living surface, current, floating, splashes
world.fluidspatches of mud and blood that take prints, ruts and splashes
world.biomesregions of one map with their own conditions, habitat, opening rules and survival effects
world.grassan instanced meadow that sways and keeps off routes and water
world.bindingsties a number of the game to a live setting of another kit through a curve

Other world.* kits are covered elsewhere or by gripforge kit api <id>: world.terrain (guide world-terrain), world.scenery (trees, rocks and cliffs dressed on a ground, instanced), world.elements (materials and states: fire, wet, frozen), world.stages (counters and stages of a changing world), world.tracks (prints and ruts), world.streaming (chunks around the player), and the structural ones (world.rooms, world.interiors, world.portals, world.platforms, world.arena, world.racetrack, world.district, world.vision, world.gravity_zones, world.magnetism, world.destructibles, world.access).

Every kit here requires game.engine (role layer or content), changes nothing until installed, and can be set per scene through the scene's layers["<kit id>"].

Turn it on #

gripforge_gamekit_install   { project_id: "gkp_…", id: "world.lighting" }
gripforge_gamekit_install   { project_id: "gkp_…", id: "world.daynight" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "world.daynight", config: { "dayMinutes": 12, "startHour": 7 } }

Only the keys that differ from the defaults need to be written. The full reference of a kit is gripforge kit api <id>.

Lighting (world.lighting) #

One kit for the light of every scene. preset is daylight, golden_hour, overcast, night or custom; custom reads the individual look fields.

KeyMeaning
sunColor, sunIntensity, sunAzimuth, sunElevationthe sun (elevation 1 to 89 degrees, azimuth -180 to 180)
skyColor, groundColor, fillIntensity, skyIntensity, environmentIntensity, exposurethe ambient light and the exposure
shadows, shadowMapSize, shadowDistancethe sun's shadows (512 to 4096, 20 to 300 m)
maxPointLights, maxSpotLights, maxShadowLightslamp budgets (8, 4; local shadows 0 by default)
activationDistance, fadeDistance, transitionSecondslamps are lit near the player and fade in and out
bloomStrength, bloomRadius, bloomThresholdHDR bloom
fogexponential height fog: density, heightFalloff, baseHeight, startDistance, maxOpacity, color, followSky
hazelinear distance haze: start, end, opacity, color (not drawn when fog has a density)
background, skyboxSlot, skyFillplain background colour, a sky panorama binding (skybox or skybox:<variant>), lifted shadows
ambientOcclusion, radianceProbes, renderQuality, colorGradingoptional web effects, each an object; omitted keeps the old rendering
antialiasing, vignette, grainfxaa or smaa, edge darkening, film grain (off on the low graphics preset)
look, looksa named look applied at start (arid, frozen, overcast, night, cinematic, or your own { id, label, values })

Lamps are documents of the world_lights collection: { id, kind: "point" | "spot", position | entity, color, intensity, range, shadows?, direction?, angle?, penumbra? }. The service (world.lighting, exclusive) offers snapshot(), configure(patch) (a patch that names a look applies it), looks(), setLight, removeLight, registerLights, unregisterLights. The live setting service world.lighting.settings exposes every ranged number of the look (nested ones dotted: fog.density), so world.bindings can drive them. The skybox asset slot takes an equirectangular panorama.

The kit emits no event and takes no decision, so it has no hook. A mod may set the look (not the render budgets) and add, patch or remove world_lights.

Day and night (world.daynight) #

KeyDefaultMeaning
dayMinutes24real minutes one game day lasts (24 means one hour a minute)
startHour8the hour of day 1 at the start
sunrise, sunset6, 19the dawn and dusk hours
runningtruethe clock runs from the start
driveLightingtruemove the sun and the sky through world.lighting (its preset becomes custom)
updateSeconds2seconds between two lighting updates

Phases are dawn, day, dusk, night. The service world.clock has hour(), day(), phase(), text(), set(hour, day?), advance(hours), pause(on?), running(), speed(mult?), sky(); it is saved with the game. Vars: world.hour, world.day, world.phase, world.time. Events: world.phase, world.hour, world.day. Script verbs: actions set_time { hour, day? }, wait_hours { hours }; conditions phase_is { phase }, time_between { from, to }. A HUD view clock is registered in the hud slot.

Hook daynight.phase { phase, from, hour, day }: asked before the clock leaves a phase (not at the start, not after a load). A tap may change hour (the clock jumps there, the next day if that hour is not later) or cancel (the clock goes back and stops if time was passing).

{ "id": "no_night", "hook": "daynight.phase", "match": { "phase": "night" }, "set": { "hour": 5.75 } }

Weather (world.weather) #

Presets: clear, snow, blizzard, rain, storm, fog, faded into each other over transitionSeconds.

KeyDefaultMeaning
preset, intensitysnow, 0.7weather at start; strength of precipitation, wind and fog
cycle, cyclePresets, cycleMinutesfalse, clear / snow / blizzard / fog, 6pick a new weather on a timer
transitionSeconds20the fade between two weathers
windDirection, gusts30, 0.4degrees from +Z towards +X; random gust strength
accumulation0.5how fast snow covers the ground (it melts afterwards, faster in rain)
slippery0.45grip lost on full snow or heavy rain: traction = 1 - slippery x cover
fogVisibilitytruefog and blizzard lower how far enemies see
cold, coldRatefalse, 1players chill in snow and blizzard
warmthTag, warmthRadiuswarmth, 6entities with this tag (braziers) warm everything within the radius
rules[]weather on conditions (below)

rules: [{ when, preset, priority?, minSeconds? }] are checked four times a second; the highest priority that holds sets its preset and keeps it minSeconds; none holding, the cycle or the fixed preset comes back. Rain while a counter is in a band:

{ "when": { "type": "counter_between", "counter": "pressure", "min": 60, "max": 200 }, "preset": "rain" }

Service world.weather (exclusive): snapshot() (preset, blend, precipitation, wind, fog, overcast, snowCover, wetness, visibility, lightning), set(preset, seconds?), traction(pos?), exposure(entity), addWarmth, removeWarmth. Vehicle and character kits multiply their grip by traction. Events: weather.changed, weather.lightning, weather.cold { entity, exposure, level } (chilled, freezing, frozen, warm). Warm zones can also be documents of warmth_sources. Optional assets: snowflake, raindrop, snow_ground. The live setting intensity is open to world.bindings.

Hook weather.change { from, to, seconds, cause } (cause: set, cycle, rule, scene): to and seconds can change, or cancel.

{ "id": "no_blizzard", "hook": "weather.change", "match": { "to": "blizzard" }, "set": { "to": "snow" } }

Atmosphere (world.atmosphere) #

The look follows a number. driver is the path of a numeric var (default counter.habitability), phases a list of looks placed along it, smoothing (6 s) how fast the world catches up with a jump. A phase is { at, name?, skyColor?, skyAmount?, sunColor?, sunIntensity?, fillIntensity?, exposure?, grass?, weather? }: colours and light glide through world.lighting, grass is the world.grass coverage, weather is a preset set once when the driver enters the phase. The default phases turn a rust-coloured dead world into a blue living one (at 0, 100, 400, 1000). With world.daynight, set its driveLighting to false so only this kit writes the sky.

Service: value(), phase(), look(), sky(), set(value | null), phases(). Event atmosphere.phase; vars atmosphere.phase, atmosphere.value; script action set_atmosphere { value } holds the look (a cutscene, a dream). Hook atmosphere.enter { index, name, from, value, weather, seconds } can change weather and seconds; it cannot cancel (hold the look with set).

Water (world.water) #

Bodies are documents of water_bodies: a river { id, points: [[x, z]…], width } (it flows from the first point to the last), a lake { id, at, radius }, or a waterfall { id, kind: "waterfall", at, yaw, width, height }; optional preset, level, flow, shallow, deep, foam, opacity. A kit that owns a waterway hands it over through world.waterways, so a MOBA river needs no data.

KeyDefaultMeaning
presetriverriver, lake, swamp, lava, ice (look of a body that names none)
flow1.2current, metres per second
opacity, foam, waves0.82, true, 0.07transparency, foam on the banks, wave height in metres
slow0.2share of their speed walkers lose in water
splashestruewhoever moves in water throws splashes
floatTagfloatingentities with this tag ride the waves and drift with a river
rise0metres added to every surface at start; live as the setting level

Service world.water: bodies(), at(x, z), heightAt(x, z), speedAt(x, z), float(entity, { draft?, drift? }), rise(). Lava hurts through combat.damage when present. Events: water.splash, water.entered, water.left, water.changed { rise }. Floating is a height and a drift, not buoyancy; nothing sinks. Hook water.enter { entity, body, preset, slow, damage }: change slow or damage for this walker, or cancel (no slow, splash or damage until it leaves the body).

{ "id": "fireproof", "hook": "water.enter", "match": { "preset": "lava" }, "if": [{ "var": "suit.on", "op": "==", "value": true }], "set": { "damage": 0 } }

Mud and blood (world.fluids) #

Patches are documents of fluid_surfaces, for example { id: "mud-alley", position: [0, 0.015, 12], size: [12, 20], preset: "mud", resolution: 192, depth: 0.13, viscosity: 0.88, recoverySeconds: 180 } (mud or blood). Use small patches (8 to 24 m); at most eight, and by default the two nearest simulate within 65 m. Keys: enabled, autoContacts (feet and four wheels), splashes, simulationRange (65), maxActiveSurfaces (2). Service: surfaces(), active(), contact({ x, y, z, yaw, radius, length, pressure, vx, vz }), reset(), interactions(after), covers(x, y, z), probe(surface, x, z), stats(surface). Event fluid.entered; hook fluid.enter { entity, surface, preset, weight } scales the pressure of an entity's contacts (weight) or keeps it out. It is a local height field, not a volumetric fluid; blood is not spawned by combat hits.

Biomes (world.biomes) #

A biome is a document of biomes: a disc { center, radius } or rectangle { rect } shape, a habitat (land, water, both), a priority (the highest wins on overlap, then the smallest), modifiers (offsets on world.stages counters), opensWhen (closed until a counter is in range, then open for good) and needs (a drain multiplier or supply per second on survival.needs gauges).

{ "id": "north_pole", "name": "North pole", "shape": { "center": [0, -120], "radius": 60 }, "modifiers": { "heat": -30 }, "needs": { "warmth": { "drain": 3 } } }

Config: default (name, habitat and modifiers of everywhere no biome covers), announce (true: emit entry and exit). Service: biomes(), at(x, z), of(entity), current(), get(id), isOpen(id), local(id | null, counter), habitatAt(x, z), randomPoint(id, rng?), contains(id, x, z), scope(id) / scopeId() (one world at a time with travel.worlds). The kit does not wall a closed biome: the game decides. Var biome.current; events biome.entered, biome.left, biome.opened; conditions in_biome, biome_open. Hooks: biome.enter { biome, name, from } (name another biome, or cancel so the player counts in none: a sealed suit) and biome.open { biome, name } (cancel to keep it closed).

Grass (world.grass) #

A deterministic meadow of instanced tufts, kept off the routes, clearings, water and paving that other kits declare.

KeyDefaultMeaning
density, maxCount2, 40000tufts per square metre; ceiling of tufts drawn
size, seed0, 11ground side in metres (0: the extent of the ground or terrain); the random seed
clearance, bank5.5, 1.5metres kept free beside a route / along the water
height, width0.7, 0.8size of a tuft (thickets are half as tall again)
color, tipColor, variation#5f9a3e, #a9cc60, 0.35blade colours
wind, fadeDistance0.8, 140sway strength; distance where it fades out
thicketstruetaller, denser grass in the stealth zones the world declares
coverage1share of the meadow shown; live setting coverage
everywherefalseon a terrain, grow on any layer, not only grass, meadow and moss

Service: placements(), look(), regenerate(), coverage(share?). Event grass.changed; it listens to scene.entered and terrain.edited. Hook grass.place { seed, density, maxCount } can change those before the meadow is placed (not cancellable).

Bindings (world.bindings) #

bindings is a list of { from, to, curve, smoothing?, step?, when? }: from is a numeric var, to is { kit, key } or { capability, key } of a live setting, curve a list of [input, output] points (linear between, flat outside), smoothing seconds of exponential glide, step the least move worth handing over (so instanced pieces are not rebuilt every tick), when a condition. After a load every output is recomputed at once.

{ "bindings": [
  { "from": "counter.habitability", "to": { "kit": "world.water", "key": "level" }, "curve": [[0, -4], [60, 0], [100, 1.5]], "smoothing": 5 },
  { "from": "counter.habitability", "to": { "kit": "world.grass", "key": "coverage" }, "curve": [[20, 0], [80, 1]], "step": 0.02 }
] }

Settings served today: world.water level, world.grass coverage, world.terrain vegetation, world.scenery coverage and coverage.<slot>, world.lighting every ranged number, world.weather intensity. Service: bindings(), set(id, enabled), targets(), force(id, input | null). The kit has no hook; a mod overrides bindings as one whole list.

Modding #

All the kits above declare their config keys moddable, and their collections (water_bodies, biomes, fluid_surfaces, world_lights, warmth_sources): a mod adds, patches or removes documents. Hooks are written as hooks documents or with engine.hooks.tap; they run on the web and Rust. Without engine content (no archetype, scene, script or story flag) no hook is called and the kit plays exactly as before.

Engines #

KitWhere it runs
world.lighting, world.weather, world.fluidsweb, native player, Godot, Unity, Unreal. The weather draws particles, fog, lightning and snow / wet surfaces natively; its rules and hook are web and Rust only. Fog, haze, grading, probes and occlusion are web render options
world.daynight, world.atmosphere, world.water, world.biomes, world.grass, world.bindingsweb and Rust (the native player); no separate Godot, Unity or Unreal delivery

When it does not do what you expect #

SymptomCause and fix
The sky ignores world.daynightdriveLighting is false, or world.atmosphere writes the sky: only one should
The lighting preset became customworld.daynight drives it; set driveLighting: false to keep your own look
Fog does not showfog needs enabled: true and a density; haze is not drawn when fog has a density
Weather rules do nothing on Godot, Unity or Unrealrules and the hook are web and Rust only
Water does not slow anyoneslow is 0, or water.enter was cancelled for that walker
Grass grows on roadsthe road is not declared by a kit (lanes.routes, world.clearings): declare it or raise clearance