Skip to content

Buildings reference

A building pack adds a place the player can buy and run. You describe it in one file, buildings/<folder>/building.xml, inside your pack; the game lists it on the Properties screen, the player buys it, moves workers in, and gives them the jobs you declared. Needs game version 1.21 or later.

Everything on this page is built and working in the game’s own source. The last section says what a building cannot do yet, so you do not plan around something that is not there.


MyPack/
package.xml
buildings/
bathhouse/
building.xml
icon.png (optional)
jobs/
attendant/ (optional: a job of your own, in the usual job format)
job.xml
messages/work.xml
bathhouse.resourcesx (optional: resources your building's flows use)

The folder name is the building’s id inside your pack: the game knows the one above as MyPack/bathhouse. Keep it lowercase with no spaces. The buildings folder name is lowercase too. An optional id="bathhouse" attribute on <Building> must repeat the folder name exactly; it adds nothing and a mismatch stops the file from loading.

Sample_Building in the game’s examples/packs folder is a complete, working example: one bathhouse with its own attendant job.

<Building>
<Name>Bathhouse</Name>
<Description>A stone bathhouse fed by a hot spring.</Description>
<Icon src="icon.png"/>
<Owner class="neutral"/>
<Rooms>6</Rooms>
<Upkeep>30</Upkeep>
<Purchase>
<Cost>3000</Cost>
</Purchase>
<Jobs>
<Job id="core/cleaning"/>
<Job id="core/general_training"/>
<Job id="MyPack/attendant"/>
</Jobs>
<Resources>
<Flow id="MyPack/towels" produce="1"/>
</Resources>
</Building>

Every element is optional. A file that says only <Building/> loads as a ten-room building with no upkeep, no jobs, and no offer for sale. Element order does not matter.

Element What it does Rules
<Name> The name on the Properties screen and inside the building. Falls back to the folder name.
<Description> Shown with the offer and at the top of the building’s screen. Plain text.
<Icon> with a src attribute The picture on the Properties screen. A png, jpg or webp inside the building’s folder. Without this line, an icon.png in that folder is used when present; otherwise a shared placeholder. A path that leaves the folder stops the file from loading.
<Media> Up to one still the game may show for the building later. <Image> entries with a role (exterior, interior, background, gallery) and a src; the first existing supported image wins. Not displayed anywhere yet.
<Owner class="..."/> Who holds it before anyone buys it. player, city, neutral or faction; absent means neutral. Buying makes it the player’s. Anything else stops the file from loading.
<Rooms> How many workers it houses. A whole number of at least 1. Default 10.
<Upkeep> Gold charged every week while the player holds it. A whole number of at least 0. Default 0. Charged on top of the empty-room cost every venue pays.
<Purchase><Cost> Offers the building for sale at that price. A whole number of at least 0. Leave <Purchase> out and the building is simply not for sale.
<Jobs><Job id="..."/> The jobs workers can hold here. Core ids such as core/cleaning, or your own pack’s jobs as MyPack/folder. The older colon spelling (core:cleaning) means the same job and still works. Every <Job> needs an id. An id the game cannot find is a warning at load, and that job never appears. A job written only for this building should leave <Filter> out of its job.xml, so it stays out of the brothel job lists.
<Resources><Flow .../> Something the building makes or uses every week. See below.
<Settings><Setting .../> A policy the player sets for each copy of this building. See below. A switch, or a number with a range.
<Flow id="MyPack/towels" produce="1"/>
<Flow id="MyPack/soap" consume="2" require="2"/>
<Flow id="MyPack/kit" produce="1" target="building"/>
  • id names a resource declared in a .resourcesx file in your pack root (or a core one such as core/beasts). In that file you write the local id only, Id="towels"; the game puts your pack in front of it, so the <Flow> here refers to it as MyPack/towels. Declaring one is the resources reference; give it a Name, because without one the player reads the raw id.
  • produce, consume and require are whole numbers of at least 0; at least one must be above 0.
  • target is estate (the default: the shared estate stock) or building (this building’s own shelf). The resource’s own StorageScope decides which is allowed.
  • If a week’s flows cannot all be paid (a consume or require short), none of that week’s flows run and the building reports it.

A setting is a question your building asks the player, once, and remembers per building. The player answers it on the building’s own screen; your jobs read the answer.

<Settings>
<Setting id="marketer_may_trade" default="false">
<Label>Let the marketer trade food for workers</Label>
<Description>While this is on, your marketer makes the trade herself when the food is there, and you read about it afterwards.</Description>
</Setting>
</Settings>
  • id is yours and is local to this building. It is what a job names; keep it short and readable.
  • default on a switch is true or false (1 and 0 are accepted as the same two answers), and nothing else: anything the game does not recognise refuses the file rather than quietly meaning false. Leave default out and the switch starts off.
  • type="number" makes it a number instead of a switch. Then min and max are required whole numbers with min at or below max, and default (if given) must lie between them; otherwise the file is refused. The player sets it with a slider on the building’s screen, and a job reads it as setting(<id>) inside a <Bind> expression (see the effects reference). A number cannot grant anything by itself: a job that spends the player’s resources still gates on a switch, and the number only shapes how far it goes. An unanswered number takes the definition’s default on a new building and on a loaded save alike. An answer the player gave is kept through a pack update; if the update narrows the range, the answer is read clamped into the new range, and the stored number is left as it was.
<Setting id="mana_reserve" type="number" min="0" max="100" default="0">
<Label>Minimum mana reserve</Label>
<Description>A worker tries a charm only if the mana left after paying for it stays at or above this.</Description>
</Setting>
  • <Label> is the line beside the switch. <Description> is the sentence underneath it. Write both as the consequence for the player, not the mechanism, because that is all they have to decide on. A setting with no <Label> loads with a warning and shows the player its raw id.
  • Declaring the same id twice refuses the file.

A job reads a setting with a condition, anywhere a <When> is allowed:

<When><BuildingSetting id="marketer_may_trade"/></When>

Two rules matter more than the syntax.

The answer belongs to one building, not to the kind. Two farms can be run differently, so a player who allows the trade at one has not allowed it at the other.

A setting that lets a job spend the player’s things should be authored default="false". Buying a building is not agreement to every policy it offers. And when you add a new setting to a building people already own, the game writes it OFF for those buildings whatever your default says, because nobody was asked. Your default applies to buildings created afterwards. If you want existing players to have it on, the switch has to be worth turning on, not turned on for them.

A job may ask about a setting the building it is working in does not offer. That is allowed, and the condition simply reads false, so nothing happens. It also means a typo fails silently; the game warns once in the log about a setting id no installed building declares.

The whole file is refused, with a message in the game log naming the field, when: <Rooms> is below 1 or not a number; <Upkeep> or <Cost> is negative, not a number, or too large; <Purchase> has no <Cost>; a <Flow> has no id, an unknown target, a negative or non-numeric amount, or no amount at all; a <Job> has no id; the id attribute on <Building> does not match the folder; an <Icon> or <Image> path leaves the building’s folder; the file contains <Type> or <JobFilter> (older drafts used them; delete them, the jobs list is the only thing that decides what runs here); or an <Entry> element (reserved for the game’s own buildings).

Elements the game does not know are ignored with a warning. <Version>, <Tiers>, <Flags>, <Capabilities>, <Removal>, <Purchase><AvailableFrom> and the unique= and category= attributes are reserved for later and ignored the same way.

A <Setting> refuses the file when it has no id, when its default is anything but true or false, or when the same id is declared twice.

  • Properties (from the Town screen and the Town Map): buildings for sale with their price, description, rooms, upkeep and jobs, and a Buy button; the player’s own buildings with a worker count and an Open button.
  • The building’s screen: name, description, rooms, upkeep, the workers with their day and night jobs, the jobs you declared (plus rest) to assign, and a Move workers button into the Transfer screen, which lists every building the player holds.
  • Weekly: the jobs run, the flows apply, the upkeep is charged, and the building’s own shift text (from your jobs/ messages) shows in the Turn Summary like any other job.
  • If your pack is removed from an existing save: the building closes but is not deleted. Its workers are moved to the Dungeon for safekeeping (they take no harm there and can be released normally), and the player is told once which building closed and which pack it needs. When the pack is installed again the building reopens with its rooms and saved records; the moved workers stay in the Dungeon until the player reassigns them.

A pack building has no marker on the Town Map; it lives on the Properties screen. There are no upgrades or tiers, no construction, no Lua hooks on buildings, no capture, and the game shows no <Media> image yet. One copy of each building per game.

The pack validator (game 1.21, unreleased) reads building.xml with the game’s own loader and reports the same refusals the game would, and on top of that the cross-checks the game only makes after loading: a flow naming a resource no package installs, a flow whose target disagrees with the resource’s scope, a job id the pack claims without shipping the folder, and the settings its jobs ask about (see the tools page). Two things it cannot settle, and says so as UNVERIFIED rather than guessing: a core job id that the game resolves through an alias in engine code, and a job id from another pack that is not installed alongside (validate the whole installation to check those). Whatever happens only in a running game, such as a purchase that fails to create the building, is still found only in the game log.