World dressing
Decision #104. The towns were alive and the world around them empty (user directive): this is
the plan for filling every location of Felucca with props, and the order of 1060 new sprites it
needs (assets/requests/world-props.md). Everything here is placed by the bake
(crates/uo-atlas/src/dress.rs), deterministically from the world seed, so the server and every
client see the same world; players change it on top (#100).
Principles
- Every place tells what happens there. A clearing has a woodcutter's stump with an axe in it, a field has its haystacks and a scarecrow, a battlefield its broken ballista and torn banners of both realms. Props come in vignettes (designed set pieces with variation), not as salt-and-pepper noise.
- Drifts, not confetti. Ground cover and flowers grow in patches chosen by low-frequency noise (a meadow has a drift of poppies here, daisies there), at a density that falls off at the patch's edge.
- Edges are where the detail is: forest edges, river banks, lake shores, beaches, the foot of every mountain, the border between realms.
- Paths stay open. Blocking props keep the 2 × 2 rule of the nature bake (at most one blocker per cell); vignettes are checked for a walkable way through.
- Budget. Wild regions stay at a few hundred statics each (flat ground cover counts least: its shadow shell is nearly empty); dense vignettes are small. Frame time is measured on the densest places before shipping.
- Real size (#74): trees 10–17 m, haystacks 3 m, a skull a hand span.
Layers
1. Biome scatter (every land tile)
Per biome: trees and big blockers (the existing nature bake), then undergrowth, ground cover (flat) and rocks, each from weighted lists by biome and climate (north/south), in noise patches:
| Biome | Undergrowth and cover | Rocks |
|---|---|---|
| forest | bracken, ferns, bluebells, violets, leaf litter, twigs, branches, pinecones/acorns, mushrooms (fly agaric, porcini, chanterelles), mossy and hollow logs, stumps, wild roses, hazel, holly | mossy |
| taiga | pine needles, juniper, blueberry, saplings, snags, birch logs, mushrooms | granite |
| Elderwood | glowing mushrooms, moss, moonflowers, glow moss, orchids, ferns, ancient roots | mossy, crystals rarely |
| jungle | tall ferns, tree ferns, banana plants, monstera, bromeliads, orchids, jungle flowers, hanging vines | mossy |
| swamp | sedge, cattails, rushes, bog cotton, pitcher plants, dead swamp trees, mangroves on the water's edge, duckweed and lilies on the water | river |
| grassland | meadow grass, poppy/daisy/buttercup/cornflower/clover drifts, dandelions, thistles, nettles, strawberries, sunflowers rarely | granite |
| steppe | dry grass, sagebrush, tumbleweed, dry bushes, lichen | sandstone |
| heath | heather (purple, white), gorse, juniper, grass tufts | granite, sandstone |
| hills | grass tufts, thistles, gorse, scree at slopes | granite |
| tundra | tundra grass, cotton grass, arctic willow, lichen, frost flowers, mammoth bones rarely | limestone, granite |
| snow, glacier | snowdrifts, snowy small pines, frozen bushes, ice blocks and spikes | snow cliffs, frozen boulders |
| beach | dune grass, shells, seaweed, starfish, driftwood | beach |
| ash lands | ash shrubs, fire lilies, sulfur moss, obsidian shards, lava crust, steam vents, fumaroles | basalt, lava rock |
2. Edges
- Rivers and lakes: cattails, rushes, horsetail and river rocks on the bank tiles; water lilies and duckweed on still water near the shore; stepping stones where a path meets a brook; washing stones near villages; fish weirs, beaver dams in the wilds.
- Coasts: driftwood, seaweed, shells, starfish, crab shells, barnacled rocks, tide pools; rarely a whale skeleton or a beached rowboat; kelp in the shallows.
- Mountains: cliff faces (
cliff_<rock>_x/_ywith corners) where rock meets walkable ground, scree and gravel at the foot, outcrops and spires, ore veins where the atlas has deposits. - Forest edges: saplings, brambles, bracken, young oaks, fallen branches.
3. Fields and farmsteads
Farmland (the atlas's fields around every settlement) is cut into plots of 8–16 × 6–12 tiles. Each plot grows one crop (by climate: rye, oats, barley and flax in the north; wheat, cabbages, turnips, onions, beans and hops in the middle; grapevines and melons in the warm south) at one growth stage (sprout, young, grown, ripe), or lies harvested (stubble with stooks, haystacks, sheaves). Plots are divided by wattle, split-rail or hedge fences with gaps and stiles, by tracks with a farm wagon or a hand cart. Some plots have a scarecrow.
Farmsteads stand among the fields of villages and along roads: a farmhouse or cottage from the building generator with its yard (haystack, granary on staddles, chicken coop, rabbit hutch, beehives, woodpile, chopping block, well sweep, manure heap, milk churns, plough and harrow). Every farming village has an orchard (rows of apple trees, a ladder, windfall apples, an apple crate), the south vineyards, and a village on a rise a windmill; one on a river a water wheel.
4. Roads
Milestones every ~400 tiles (in the realm's style), signposts at junctions, wayside shrines of the realm every ~1500 tiles, lanterns on the last stretch before a town, benches and wells near villages, border posts where a road crosses into another realm (toll barriers on highways), bridges where a road fords a river (stone in the realms, wood in the wilds: deck pieces over the ford, parapets or railings, piers), and now and then a broken wagon, a dropped crate, a traveller's pack or a memorial cross (more where the danger is high).
5. Towns
On top of the town plans (#103): stalls by trade with their goods in the market squares, trade signs by trade at the doors (smith, inn, bank, tailor, baker, butcher, alchemist, mage, healer, bowyer, jeweller, carpenter, guild, provisioner, stable), banners and wall flags of the town's realm, lamp posts in the realm's style, flower boxes under windows in rich quarters, laundry lines between houses in poor ones, crates, barrels and sacks by warehouses and inns, building works (scaffolding, beams and bricks) on some free plots, puddles and rubbish in back streets.
6. Places of interest (vignettes)
| Place (count at seed 1) | Vignette |
|---|---|
| ruin (650) | a ruined building of the Old Empire or a later war: rooms of ruined walls in the region's wall set, rubble, columns, a toppled statue, floor patches, overgrowth; bones where it is dangerous |
| hermit's hut (353) | a cottage from the generator, herb garden, goat pen, drying racks, mortar on a stump, bee skep, woodpile, wind chimes or bone charms |
| shrine (352) | one of the eight virtue shrines on a paved dais, votive candles, offering bowls, prayer flags, benches; in the realms their own altars |
| monster lair (236) | the camp's monsters (#100) plus a nest of bones, gnawed bones, carcasses, claw marks, skulls, webs or slime by biome |
| bandit camp (234) | the camp (#69) plus ragged tents, loot piles, a wanted board, a card table, a ransom cage, a lookout, stake palisades |
| standing stones (131) | a stone circle (menhirs, a few fallen, trilithons in the big ones), an ancient altar in the middle, rune stones, heather and flowers |
| graveyard (128) | a fenced yard of graves in rows (mounds and stones of the realm), a tomb or mausoleum, an open grave with a shovel, dead trees, candles |
| ancient tree (127) | the ancient tree, its root ridges, ribbons of offerings, a carved face, glow moss and a ring of mushrooms |
| wizard's tower (74) | a tower from the generator, an arcane circle, crystal pylons, an astrolabe, a telescope, a bubbling cauldron, rune pillars, floating books, ward posts |
| watchtower (71) | a tower from the generator, a stake palisade, a signal beacon, a weapon rack, the realm's banner, a campfire |
| abandoned mine (63) | a mine entrance into the nearest rock, rails, ore carts, tailings, broken supports, tools, a skeleton |
| orc camp (57) | the camp plus orc huts, totems, bone fences, a war drum, a fire pit, a cage, a crude throne, trophy racks |
| battlefield (55) | a wide field of the war: torn banners of both realms, broken siege engines, weapons in the ground, shields, skeletons in armour, horse skeletons, scorch marks, stake fields, a mass grave and a memorial |
| shipwreck (52) | a hull on the beach, its bow or stern, a fallen mast, barrels, crates, a sea chest, a cannon, skeletons, driftwood |
| fey ring (36) | a fairy ring of mushrooms, moonflowers, fey stones, wisps, a branch arch, a mushroom house |
| waystone (23) | a waystone on a paved circle with benches |
| inn (17) | an inn from the generator with a stable yard: hitching rails, troughs, hay, a wagon, its sign and lanterns, a well |
| lighthouse (1) | the lighthouse and a beacon on the rocks |
7. Dungeon entrances
Every dungeon of the atlas (166) gets its entrance sprite (entrance_<kind>) facing the
camera, a trodden approach, and its dressing: carts and rails at mines, cairns and grave mounds
around barrows, a graveyard around a crypt, bones at caves, half-sunk columns at sunken temples,
fey lights at fey hollows, lava crust and scorch at fire lairs, ice at ice caves, barnacled rocks
at sea grottos, ruined walls at ruined keeps, and around the Old Capital the ruins of a whole
city behind its triumphal gate. Warning skull posts and braziers (green at crypts) mark the
dangerous ones.
8. Resource nodes
The atlas's deposits become things to gather: ore veins of the nine ores and quarry faces on rock
at the foot of mountains, gems in the deep places, reagent plants (mandrake, nightshade,
ginseng, garlic, blood moss, spider silk, black pearls, sulfurous ash) in their biomes. Gathering
itself is later work (resource-items).
9. Danger
The encounter zones' danger raises the share of grim props: more bones, skulls, broken carts and graves where the roads are unsafe, battle debris along the frontier, skull posts and totems in the wilds, pirate flags, cannons and rum barrels on the isles' coasts.
Built
Code: crates/uo-atlas/src/dress/ (props.rs the order as a table, scatter.rs per region,
sites.rs the vignettes), town dressing in towns.rs. Run:
cargo run --release -p uo-atlas -- --no-tiles --out /tmp/atlas --bake assets/world/felucca # ≈ 25 s
cargo run --release -p uo-atlas -- --plans-only --out /tmp/x --sites-near 10102,3599 # what was planned near a point
python3 tools/world_props_usage.py # every ordered prop has a rule
cargo test --release -p uo-atlas # landmarks kept, doors free, bake reads back
- The 1060 props were modelled by nine parallel sessions, one per group, and merged:
1698 sprites in the catalog now (156 MB).
tools/world_props_usage.pychecks that every one of them is placed by some rule. - Rules worth knowing: random clutter takes either orientation (
_s↔_e, direction-free_x↔_y,props::twin); a site whose centre is on rock or water moves to the nearest open ground within 30 tiles, and its landmark goes to the nearest spot where it fits (Site::put_near); sites clear a glade (no trees within 6–12 tiles, 26 on battlefields, which also trample their fields); earlier, more important sites win where two overlap; blockers never wall a free tile in and keep the 2 × 2 rule; nothing blocking stands on or next to a front door. - Blocking: multi-tile blockers block their whole footprint (statics chunks carry the
extra tiles); ruined walls, cliffs, palisades, barricades, bridge parapets, portcullises and
sealed doors block their edge like walls (
blocked_edges); toll and road-repair barriers stand beside the road and block nothing. - Water props (
props::on_water) stand on water tiles: plants of the shallows, boats, piers and docks, bridge piers, the water wheel, ferries. Docks and boats are not walkable yet (the server treats water as unwalkable); bridges stand on the road's ford, which is. - Shadows: sprites lower than 0.4 units (ground cover, flowers, pebbles, shells) cast no shadow shell; that halved the cost of a dressed meadow.
Numbers
Seed 1: 13.97 M statics (6.8 M before the dressing), 4232 sites (636 ruins, 347 shrines, 372 farmsteads, 128 graveyards, 125 ancient trees, 124 stone circles, 966 work camps at deposits and fishing villages, 89 orchards and vineyards, 66 windmills, 16 watermills, 15 harbours, …). Statics per land region: mean 465 → about 530, the capitals 4000–5600.
Frame time (2560×1600, zoom 4, headless, a busy machine with load 8–15: compare within these runs only, #49):
| Place | Statics streamed | Frame |
|---|---|---|
| meadow near Skartor (drifts, fields at the edge) | 8 467 | 7.6–9.3 ms |
| farmland | 10 600 | 10.1–10.3 ms |
| the middle of Skartor | 13 544 | ≈ 15 ms |
| dense forest | 2 345 | 24–26 ms |
The forest's cost is its real-size trees (22 ms before the dressing); the dressing adds little there.
Not done yet
- Docks, piers and boats can't be walked on; no ships to sail.
- Field crops are one static per tile; growth stages don't advance with time (the world is static, #100).
- Resource nodes are only scenery until gathering exists (
resource-items).