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.
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 #
| Kit | What it gives the game |
|---|---|
world.lighting | the sun, the sky, the lamps, fog and haze, bloom, ambient occlusion, grading, named looks |
world.daynight | a clock (hours, days, dawn / day / dusk / night) and a sun that follows it |
world.weather | snow, blizzard, rain, storm, fog; snow cover, wet ground, traction, visibility, cold |
world.atmosphere | the look of the world follows a number of the game (sky, sun, grass, weather) |
world.water | rivers, lakes, lava and ice with a living surface, current, floating, splashes |
world.fluids | patches of mud and blood that take prints, ruts and splashes |
world.biomes | regions of one map with their own conditions, habitat, opening rules and survival effects |
world.grass | an instanced meadow that sways and keeps off routes and water |
world.bindings | ties 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.
| Key | Meaning |
|---|---|
sunColor, sunIntensity, sunAzimuth, sunElevation | the sun (elevation 1 to 89 degrees, azimuth -180 to 180) |
skyColor, groundColor, fillIntensity, skyIntensity, environmentIntensity, exposure | the ambient light and the exposure |
shadows, shadowMapSize, shadowDistance | the sun's shadows (512 to 4096, 20 to 300 m) |
maxPointLights, maxSpotLights, maxShadowLights | lamp budgets (8, 4; local shadows 0 by default) |
activationDistance, fadeDistance, transitionSeconds | lamps are lit near the player and fade in and out |
bloomStrength, bloomRadius, bloomThreshold | HDR bloom |
fog | exponential height fog: density, heightFalloff, baseHeight, startDistance, maxOpacity, color, followSky |
haze | linear distance haze: start, end, opacity, color (not drawn when fog has a density) |
background, skyboxSlot, skyFill | plain background colour, a sky panorama binding (skybox or skybox:<variant>), lifted shadows |
ambientOcclusion, radianceProbes, renderQuality, colorGrading | optional web effects, each an object; omitted keeps the old rendering |
antialiasing, vignette, grain | fxaa or smaa, edge darkening, film grain (off on the low graphics preset) |
look, looks | a 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) #
| Key | Default | Meaning |
|---|---|---|
dayMinutes | 24 | real minutes one game day lasts (24 means one hour a minute) |
startHour | 8 | the hour of day 1 at the start |
sunrise, sunset | 6, 19 | the dawn and dusk hours |
running | true | the clock runs from the start |
driveLighting | true | move the sun and the sky through world.lighting (its preset becomes custom) |
updateSeconds | 2 | seconds 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.
| Key | Default | Meaning |
|---|---|---|
preset, intensity | snow, 0.7 | weather at start; strength of precipitation, wind and fog |
cycle, cyclePresets, cycleMinutes | false, clear / snow / blizzard / fog, 6 | pick a new weather on a timer |
transitionSeconds | 20 | the fade between two weathers |
windDirection, gusts | 30, 0.4 | degrees from +Z towards +X; random gust strength |
accumulation | 0.5 | how fast snow covers the ground (it melts afterwards, faster in rain) |
slippery | 0.45 | grip lost on full snow or heavy rain: traction = 1 - slippery x cover |
fogVisibility | true | fog and blizzard lower how far enemies see |
cold, coldRate | false, 1 | players chill in snow and blizzard |
warmthTag, warmthRadius | warmth, 6 | entities 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.
| Key | Default | Meaning |
|---|---|---|
preset | river | river, lake, swamp, lava, ice (look of a body that names none) |
flow | 1.2 | current, metres per second |
opacity, foam, waves | 0.82, true, 0.07 | transparency, foam on the banks, wave height in metres |
slow | 0.2 | share of their speed walkers lose in water |
splashes | true | whoever moves in water throws splashes |
floatTag | floating | entities with this tag ride the waves and drift with a river |
rise | 0 | metres 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.
| Key | Default | Meaning |
|---|---|---|
density, maxCount | 2, 40000 | tufts per square metre; ceiling of tufts drawn |
size, seed | 0, 11 | ground side in metres (0: the extent of the ground or terrain); the random seed |
clearance, bank | 5.5, 1.5 | metres kept free beside a route / along the water |
height, width | 0.7, 0.8 | size of a tuft (thickets are half as tall again) |
color, tipColor, variation | #5f9a3e, #a9cc60, 0.35 | blade colours |
wind, fadeDistance | 0.8, 140 | sway strength; distance where it fades out |
thickets | true | taller, denser grass in the stealth zones the world declares |
coverage | 1 | share of the meadow shown; live setting coverage |
everywhere | false | on 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 #
| Kit | Where it runs |
|---|---|
world.lighting, world.weather, world.fluids | web, 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.bindings | web and Rust (the native player); no separate Godot, Unity or Unreal delivery |
When it does not do what you expect #
| Symptom | Cause and fix |
|---|---|
The sky ignores world.daynight | driveLighting is false, or world.atmosphere writes the sky: only one should |
The lighting preset became custom | world.daynight drives it; set driveLighting: false to keep your own look |
| Fog does not show | fog needs enabled: true and a density; haze is not drawn when fog has a density |
| Weather rules do nothing on Godot, Unity or Unreal | rules and the hook are web and Rust only |
| Water does not slow anyone | slow is 0, or water.enter was cancelled for that walker |
| Grass grows on roads | the road is not declared by a kit (lanes.routes, world.clearings): declare it or raise clearance |