Reusing the dungeon's notes, bodies and chests in houses
Houses can now hold a note, a dead body, a chest with a word lock and a look spot, and they remember what was taken even after the house is unloaded.
A house in the game can now hold the same things a dungeon holds. There’s a note on the floor to pick up and read, a dead body that says a line the first time you look at it, a chest locked by a word on a keypad, and a spot that gives a line when you press E near it. A taken note stays taken and an opened chest stays open, even after the house has been unloaded and built again. All the words in the film are test text, so I haven’t judged any of the writing yet.
Why did the contraband rooms have nothing in them?
The houses already had hidden rooms behind a bookcase or a trapdoor, and there was nothing to find in them. The dungeons already had notes, bodies, keypads and chests, so I wanted to reuse those and not write a second version for buildings. This is the generic half of the work. The words for the rooms are a separate item, so everything here is placeholder.
How do you lay a dungeon’s things in a house?
Nothing is copied. The note pickup, the NPC body, the chest and its lock already do the work, so a new class, BuildingHooks, only builds them. You call BuildingHooks.lay(cell, b, hooks) with the building’s cell, its index in that cell, and an array of dictionaries in the same shape the dungeon content files use. Every position is in the building’s space, with an optional turn in degrees.
BuildingHooks.lay(cell, b, [
{"kind": "look", "at": Vector3(1, 0, 2), "name": "Tubes", "look_text": "...", "height": 1.2},
{"kind": "note", "at": Vector3(0, 0.9, 1), "item_name": "Weigh Slip", "read": "..."},
{"kind": "body", "at": Vector3(-1, 0, 0), "turn": 90, "name": "Sexton", "body_text": "..."},
{"kind": "lock", "at": Vector3(2, 0, 0), "what": "Feed Cabinet", "code": "YIELD", "holds": ["juice_small"]},
])
There are five kinds. A note becomes a DungeonPickup, so it goes into the inventory, opens the note screen by itself and counts as read. A body is an NpcBody that says its text on the first look. A lock is a Chest whose lock has a code, either one to eight digits or a word of three to eight letters. A word is keyed on the level’s keypad the way a dungeon’s word door is, so YIELD is typed as letters. A look is a small new class, BuildingLookSpot, that says its words when you press E and sends them to the event log. A lock can carry a note with it, laid next to the chest, which is how the film’s weigh slip carries the word for the cabinet.
Everything goes under one holder node per building, a child of the cell, so it’s freed with the cell. A hook with an unknown kind, a code no keypad takes or a note with no words prints a warning and is skipped.
Why does a house forget what was taken?
This was the real problem. A dungeon level is loaded once and its things are named by its file. The world streamer creates and frees a building as the party walks past, and a node gets a new name each time, so a saved “this note was taken” had nothing to attach to.
The fix is to name each thing by its place, the way the doors in a building already were. A building’s id is cell_<x>_<z>_b<b>, where x and z are the cell’s position in 64 meter steps and b is the building’s index in the cell. A thing’s id is that, then its kind, then its number among the hooks of that kind, for example cell_2_3_b0_note0. Laying the same plan in the same cell gives every thing the same name in every run. A taken note goes in the dungeons’ list of taken things, and a chest’s contents and lock go in the same two save sections the dungeon chests use.
While a house is away, its holder belongs to the streamer’s limbo, the same place terrain chunks keep their state. lay registers the holder with learn, restores what was captured last time with apply, and a handler on tree_exiting calls capture when the holder leaves the tree. If the world has no streamer, as in a test bench, nothing is kept.
How does a note made inside a house read after a load?
In a dungeon a note is an item the item database makes from a generator. A note laid inline in a house had no item, so BuildingNotes makes one from the hook’s id, name and text, and the item database is regenerated when a new one appears. Notes written in files under content/buildings/ are read before a save’s inventory is made, so a note carried out of a house still reads after a load. A note that’s only declared while the game runs reads after a load only once that house has been built again in that run. I haven’t fixed that for now. A body also carries nothing yet, so searching one gives you nothing.
What did the judge say?
It agreed, with three small notes. In the film the look spot sits on bare floor and not on a prop that matches its words, so when the real words go in it should stand on a matching prop. Two prompts are hard to read under the caption bar, which is about how I framed the film. And “taken stays taken, open stays open” is said in the film but not shown, because the film never leaves the house and comes back. The new test covers that part and passed 32 checks with none failing. The existing building, dungeon, note and chest tests passed too, 59 in all. building_assembly ran slow in the crowded parallel run and passed when I ran it alone.