Mud and blood

Usage guide of world.fluids: editable mud and blood patches that take footprints, wheel ruts and splashes; the fluid_surfaces documents, settings and defaults, service, events, the fluid.enter hook, saves and engines.

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

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

Mud and blood patches in your world (world.fluids) #

Small patches of mud or blood that remember who walked or drove through them. Readable offline: gripforge docs world-fluids, or the MCP tool gripforge_docs (topic world-fluids). The other environment kits (light, weather, water, grass) are in the environment guide.

What it is for #

world.fluids simulates a height field per patch. A foot or a wheel pushes the surface down and piles a rim beside the print; the surface then slowly relaxes. The patch is drawn as a mesh whose heights follow the simulation (ruts, rims, wet shine). It is a local surface effect, not a volumetric fluid: the existing ground stays the collision surface, and nothing sinks or flows. Blood is not spawned by combat hits: the game places a blood patch where it wants one.

Turn it on #

Install the kit and add patches as fluid_surfaces documents (in the project, or in a scene's data):

{ "id": "world.fluids", "config": {} }
{ "fluid_surfaces": [{ "id": "bog", "position": [0, 0, 0], "size": [10, 8], "resolution": 64 }] }

It requires game.engine. Do not install it with world.tracks in the same scene: they conflict (the same-scene overlap is reported).

First example #

<!-- test: kits/game_engine/host/tests/world_fluids.rs::a_walker_leaves_prints_in_the_active_patch --> A player walks along a patch named bog. The patch is active (it is near the player), the walker leaves prints, and the save remembers that the player stands in bog.

{ "op": "call", "service": "world.fluids", "method": "active", "args": [] }
{ "op": "call", "service": "world.fluids", "method": "stats", "args": ["bog"] }

active answers ["bog"]. After thirty steps of walking, stats answers a trough below -0.01 (the deepest print) and a positive peak (the rim).

Settings and defaults #

SettingTypeDefaultMeaning
enabledbooleantrueturns the whole kit off (no patch, no contact)
autoContactsbooleantruefeet and wheels of entities leave prints on their own
splashesbooleantruecontacts also throw droplets
simulationRangenumber65metres from the player within which a patch is relaxed (20 to 120)
maxActiveSurfacesinteger2how many patches are simulated at once, the nearest first (1 to 4)

A scene may override these through its layers["world.fluids"] entry.

The fluid_surfaces collection #

At most eight patches per scene. A patch that is invalid, a duplicate id, or over the limit is left out and a warning is logged.

KeyDefaultMeaning
idrequiredunique name (1 to 80 characters)
positionrequired[x, y, z] in metres; place it just above the ground
sizerequired[width, length] in metres, each 2 to 48; 8 to 24 m patches give the best detail
yaw0rotation in radians
presetmudmud or blood
resolution128grid cells per side: 64, 128 or 192
depth0.13visible layer thickness, 0.02 to 0.35
viscosity0.88higher keeps ruts and folds longer, 0 to 1
recoverySeconds180slow return to rest; 0 disables recovery
seed1random seed of the resting surface

Services, events, hooks #

  • world.fluids (service): surfaces() the patches, active() the ids being simulated, contact({ x, y, z, yaw, radius, length, pressure, vx, vz, entity? }) presses the surface (answers the volume moved; 0 if a number is missing or not finite), reset(surface?) restores one patch or all, interactions(after) the recent contacts after a sequence number, covers(x, y, z) whether a point lies on a patch, probe(surface, x, z) the surface height or null outside, stats(surface) the volume, peak, trough, revision and active of a patch (null if unknown). fields() and heights() give the patches as plain data for a renderer.
  • fluid.entered (event): an entity made its first contact in a patch. Payload: entity, surface, preset.
  • fluid.contact (event, listened to): other objects may send the same contact shape as contact().
  • fluid.reset (event, listened to): { surface? }; omit it to reset every patch.
  • fluid.enter (hook): { entity, surface, preset, weight }, asked once per stay, before the first print. Change weight (0 to 1) to scale the pressure of all the entity's contacts in that patch (0.3 for a light step), or cancel it: the entity leaves no print and no splash, and fluid.entered is not emitted, until it leaves the patch and comes back.
{ "id": "light-feet", "hook": "fluid.enter", "match": { "preset": "mud" }, "set": { "weight": 0.3 } }

Modding #

A mod can override the five settings and add, patch or remove fluid_surfaces documents. Hooks run on the web and the native player. Without a tap the kit plays exactly as before.

Saves #

The save keeps each patch (only the cells that left rest), who walked where, which patch each entity stands in, and the recent splashes. A patch that belongs to a scene is kept per scene while another scene is played.

Engines #

The solver, the contact samplers and the save format are the same on the web, the native player, Godot, Unity and Unreal; each engine draws the patches with its own mesh and droplets. With world.tracks in the same scene the patches would be drawn over the snow prints.

When it does not do what you expect #

  • No print appears: the patch is not in active() (too far: raise simulationRange or maxActiveSurfaces), autoContacts is off, or a fluid.enter tap cancelled the entity.
  • A patch is missing: the log says it is invalid, a duplicate, or over eight patches.
  • contact() answers 0: a field is missing or not a finite number, or the kit is not enabled.
  • Prints vanish too fast or never: change recoverySeconds and viscosity.

Limits #

A height field per patch, 48 m at most per side, eight patches per scene and four simulated at once. No flow, no buoyancy, no blood from combat.

Versions #

Kit 1.3.0 (service contract 1.1.0). Hook fluid.enter since 1.3.0; native Godot, Unity and Unreal deliveries since 1.1.0; scene patches since 1.2.0.