Room dressing
Small objects on furniture surfaces (papers on desks, a kettle on the worktop, glasses on the bar) chosen per venue in .uldressing files.
Once a room's furniture stands, the game puts small things on it: papers and a mug on a desk, a lamp and a book on a bedside table, a kettle and a chopping board on the kitchen worktop, beer mats and glasses on a bar, a card terminal on a shop counter. Which objects go on which surfaces is mod data, in .uldressing files.
You never place a mug by hand. A rule says "on desks in a police station, 2 to 5 things out of radios, files, mugs and evidence bags", and every desk of every police station gets its own mix. The same building always gets the same objects.
How it works
- Every generated piece in the room that has a surface is a possible host: its catalog entry has
levels(the surfaces something can stand on, see Rooms) or at least asurfaceheight. - For each host, the most specific rule whose
ONmatches it is used. A rule takes the levels it names (LEVEL), and a later rule can still use the host's other levels. - The rule rolls how many things go on each level (
COUNT, capped byDENSITY, both scaled by the room's personality), draws each one fromPROPS, and looks for a free spot on that level, away from the edge and from anything already standing there. - Each object is a separate piece in the room, like any other node of a set, so a hand can pick it up (
Actor:PickUp("Mug")) when the catalog marks ithandheld.
What is placed depends only on the building's seed, the furniture group and the rule. Moving a desk in build mode re-dresses that desk alone.
Objects come from the room's own sets first, so they match its style, then from the sets in PROP_SETS. A piece is a possible object when it is a generated piece, not wall-hung, and no larger than 90 cm.
A dressing file
lua-- Rooms/Dressing/police.uldressing
return {
NAME = "police",
VENUES = { "police" }, -- venue tags; or GRAMMARS = { "cid_office", ... }
BASE = "office", -- take the office rules first
RULES = {
{ ID = "desk", ON = { "Desk" }, LEVEL = "top", EDGE = "any",
COUNT = { 2, 5 }, CHANCE = 0.95, DENSITY = 6,
PROPS = {
{ LEAD = "Product/Radio", MATCH = { "Transistor", "DAB" }, WEIGHT = 0.6, MAX = 1 },
{ LEAD = "Product/Folder", WEIGHT = 3, MAX = 3 },
{ LEAD = "Product/Mug", WEIGHT = 2, MAX = 2 },
{ LEAD = "Product/EvidenceBag", WEIGHT = 1.5, MAX = 2 },
} },
{ ID = "custody_desk", ON = { "Counter/CustodyDesk" }, LEVEL = "all",
PROPS = {
{ LEAD = "Product/CardTerminal", MAX = 1, REQUIRED = true },
{ LEAD = "Product/Clipboard", MAX = 1 },
} },
},
}
The files live in Rooms/Dressing/*.uldressing in any mod. They are Lua tables, like grammars.
File fields
| Field | Meaning |
|---|---|
NAME |
The file's name. A later mod's file with the same NAME replaces it. Defaults to the file name. |
VENUES |
Venue tags this file is for (police, cafe…). |
GRAMMARS |
Grammars this file is for (cid_office, shop_counter…). A file is used when the venue or the grammar is listed. A file with neither applies to every room (the base game's _default.uldressing). |
ROOMS |
Optional: only these rooms of a multi-room venue ({ "cid", "custody" }). |
BASE |
Another file's NAME whose rules come first. |
MAX_PROPS |
The most objects one room gets (default 150). |
PROP_SETS |
More sets objects may come from, after the room's own: { "Sets/GenProps" }. |
RULES |
The rules, below. |
Which rule wins. The rules of every file that applies are gathered: files for every room first, then the files that name the venue or the grammar. A rule ID seen again replaces the earlier rule, so a venue file can redefine the generic desk rule for its own desks. On each host, the rules are tried from the most specific (the last gathered) to the most generic. A rule with OFF = true switches an inherited rule off.
Rule fields
| Field | Meaning |
|---|---|
ID |
The rule's name, for replacing it in a later file. |
ON |
The host's kind, "Category" or "Category/Type" as in the catalog ("Desk", "Table/Nightstand", "Counter/Bar"). Any of them. |
ON_MATCH |
Optional words, one of which must be in the host piece's name ({ "Cafe", "Bistro" }). |
ON_ZONE |
Optional grammar zones the host's group was placed in ({ "counter" }). |
NOT_MATCH |
Optional words that rule a host out when its piece name has one ({ "Stocked", "Bottles" }: displays with their goods modelled in). |
LEVEL |
"top" (the main top, default), "shelves" (every level below it), "all", or a number (2 = the second level from the floor). |
EDGE |
Where on the level: "front" (the edge a person stands at), "back" (against the wall), "seats" (in front of each seat of the group, turned towards it), "any" (default). |
COUNT |
{ min, max } objects per level, or one number. Default { 1, 2 }. |
CHANCE |
Chance that a host gets anything from this rule (0 to 1, default 1). |
DENSITY |
At most this many objects per square metre of the level (default 6). |
MAX_SIZE |
The largest object this rule may place, in cm along its longest side (default 90: dressing is small things). Raise it for a rule that stocks a warehouse rack's ground deck with pallets and flat-pack boxes. |
PROPS |
What may be placed, below. |
STOCK |
"shop": instead of PROPS, what the venue's shops sell (see Shop stock). |
FILL |
With STOCK: the share of runs that are stocked, the rest left as gaps (0 to 1, default 0.8). |
MANNEQUIN |
Instead of objects on the host, a live mannequin in place of the display figure baked into it, dressed from the venue's clothes stock (see Shop mannequins). |
COUNT and DENSITY grow with the room's PERSONALITY.CLUTTER and shrink with its CLEANLINESS (from the .ulroom): a squat's desk is fuller than a bank's.
Prop fields
| Field | Meaning |
|---|---|
LEAD |
The object's kind, "Category/Type" from the catalog ("Product/Mug", "Appliance/Kettle", "Lighting/TableLamp"). One string or a list. |
MATCH |
Optional words, one of which must be in the piece's name. |
WEIGHT |
How often it is drawn against the others (default 1). |
MAX |
At most this many on one host (default: no limit). |
REQUIRED |
Placed first on every host the rule dresses (a card terminal on a till). |
An object is only placed where it fits: lower than the free height above the level (a shelf under another shelf), inside the level, and not over anything already there.
Shop stock
A rule with STOCK = "shop" fills its hosts with the goods of the venue's shops: every item of the venue's .ulshop files whose .ulitem has a Piece: that matches a piece of the room's sets or PROP_SETS. On each level, COUNT runs of one item stand side by side along the front edge (2 to 6 of the same, like a faced-up shelf; a double-sided gondola's far half faces the other aisle), the item drawn with cheap things more often than dear ones. Each object is the shop's stock: buying one takes one off, a limited line shows no more than the shop has left, and they come back when the shop restocks (see Stock on the shelves).
lua{ ID = "shop_stock", ON = { "Display/Gondola", "Display/Shelf", "Storage/Shelf", "Display/Showcase" },
NOT_MATCH = { "Stocked", "Bottles", "Full" }, LEVEL = "all", STOCK = "shop", COUNT = { 2, 5 }, FILL = 0.85 },
What the game leaves alone
- A level that already carries products from its group (the laid café tables, a counter with its till) is not dressed again.
- Objects are never tinted: the furniture materials are shared by every room.
- Furniture from the old packs (not generated) has no measured surfaces and is not dressed.
Shipped files
| File | For |
|---|---|
_default.uldressing |
Every room: desks, vanities, bedside, side, dining and coffee tables, kitchen worktops, sinks, bookcases, shelves, dressers, TV units |
office.uldressing |
Offices: monitors and keyboards, meeting tables, reception, filing cabinets |
police.uldressing |
Police stations (on top of office): radios, files, evidence bags, the custody desk, interview tables |
shop.uldressing |
Shops (by grammar): a card terminal and till items on the counters, and the shop's own stock on its empty displays |
bar.uldressing |
Bars, pubs, clubs: glasses and beer mats |
cafe.uldressing |
Cafés and restaurants: cups, plates, napkins on bare tables; the counter |
hotel.uldressing |
Hotel rooms and the front desk |
hospital.uldressing |
Ward tables, nurses' stations, clinical trolleys |
school.uldressing |
Exercise books and pencils on desks |
home.uldressing |
Homes: the post and bills that collect on dining, side and hall tables (repeats _default's rules for those hosts, plus the paperwork) |
mannequins.uldressing |
Clothes shops (by grammar): live mannequins on the display figures, dress forms and busts |
funeral.uldressing |
Funeral directors': orders of service, funeral flowers, tissues and sympathy cards on the tables; the director's desk |
To check your files, run python Tools/RoomKitExport/check_dressing.py from the game's folder: it lists the PROPS that name no piece and the rules whose ON matches no piece with a surface.
The objects are real
Every object the dressing places can be clicked: taken into the inventory, picked up in a hand, put down elsewhere (see Things in rooms). The dressing comes out the same on every visit, so the game only saves what the player changed, per building and room, and applies it right after the dressing. Which item an object is comes from an .ulitem's Piece: or from Items/room_objects.json.
In a shop, the objects of a STOCK rule are what the shop sells: buying takes them off the shelves (see Stock on the shelves).