Skip to content
TAURION
06Buildings

Buildings

Construction, foundations, ancient buildings and what each one does.

For players: what this is in one minute#

Buildings are the bases you and the three factions plant on the map. You start a building as a cheap foundation (it has almost no health and does nothing), then haul materials into it to finish it into a full building. A finished building gives you services — refining ore, repairing armour, copying blueprints, building items and vehicles — and you (the owner) can charge other players a fee to use it. The map also already has indestructible Ancient (neutral) buildings: giant obelisks and the three faction capital "cities" clustered around each side's spawn point. If a player building's health hits zero it can be destroyed, and most of what was stored inside is lost.

Each faction has a lore name and a colour code: RED = Jodon, GREEN = Ephrati, BLUE = Reubo. Internal item/building codes (like r cc) appear throughout this doc next to their display names (like the Jodon Command Centre) so both players and developers can follow along.

There are 66 building types defined in total: 59 used in the live game (3 obelisks, 3 ancient hubs, and the per-faction set of player-buildable and city buildings) plus 7 test-only types (regtest; see §12). The full breakdown is in §0 and the catalogs in §3, §4, §7, and §13.


Authoritative reference for every building type and every building mechanic in Taurion. All rules are sourced from the Game State Processor (GSP) — the server program that computes the game's official state from on-chain moves, and the single source of truth. Human display names are the building names shown in the official client (which port the original Unreal naming); item/vehicle display names are likewise the ones shown in the official client.

Jargon used below, defined once here: HP = hit points (health); milli-HP = HP × 1000 (the GSP stores HP in thousandths for precision); L1 distance = hex grid "taxicab" distance; vCHI = the in-game currency that is burnt (destroyed) to pay base service costs; Cubits = the tradable token used on the DEX (the in-building decentralized exchange / order book); BP = blueprint; bps = basis points (1 bp = 0.01%).

Unless noted, all citations are file:line into the GSP source tree.


0. Naming, factions, and internal codes#

Internal building "type" strings are short codes such as r cc, g rf, b vb. The first token before the space is the faction prefix, the rest is the building-class code.

Faction prefixes#

Prefix Faction (game state) Client lore name Source
r RED Jodon proto/roconfig.cpp:165-170
g GREEN Ephrati same
b BLUE Reubo same
(none) ANCIENT Ancients / neutral obelisks & ancient buildings

The faction of a building type is inferred at runtime from the prefix, but only for building types that contain a construction block (i.e. the player-buildable ones). The inferred faction is written into construction.faction (proto/roconfig.cpp:165-170 for the prefix table, 187-211 for the inference). A building's instance faction is immutable and stored in the DB (database/building.hpp:69-70).

Complete type inventory (the count)#

Across all proto/roconfig/buildings/*.pb.text files there are 66 building_types definitions:

Group Count Types
Obelisks 3 obelisk1, obelisk2, obelisk3
Ancient hubs 3 ancient1, ancient2, ancient3
RED production 18 r cc,r cf,r rf,r r,r rt,r vb,r ss, r c1r c11
GREEN production 17 g cc,g cf,g rf,g r,g rt,g vb,g ss, g c1g c10 (no g c11)
BLUE production 18 b cc,b cf,b rf,b r,b rt,b vb,b ss, b c1b c11
Live-game subtotal 59 (3 + 3 + 18 + 17 + 18)
Test-only (regtest, test.pb.text) 7 checkmark, itemmaker, carmaker, huesli, r test, g test, b test
Total 66

Note GREEN has only c1c10 (10 common buildings) while RED and BLUE each have c1c11 (11). The 7 test types reference two dummy construction materials, foo and zerospace, that exist only for tests.

Building-class codes#

Code Class (display) Player-buildable? Notes
cc Command Centre Yes Also the faction spawn building
cf Construction Facility Yes
rf Refinery (research/reveng) Yes "rf" offers blueprint copy + reverse-eng
r Refinery (ore refining) Yes the ore-refining service building
vb Vehicle Bay Yes
rt Rocket Turret Yes only building with an offensive attack
c1c11 Common building No decorative ancient city buildings only
ss City No type defined but never placed (legacy)
obelisk1/2/3 Ancient Obelisk No initial neutral landmarks
ancient1/2/3 Ancient Building No type defined but not placed in initialbuildings

Client-only codes: the official client also lists sf (Research Facility), ep (Energy Plant) and et (Energy Turret). These do NOT exist as GSP building types — there are no *_sf/_ep/_et.pb.text files. They are leftover client model mappings and have no game effect.

Display name for an instance = faction lore name + class name, e.g. r cc shows as the Jodon Command Centre in the game UI. Worked examples across the factions: g cf = Ephrati Construction Facility, b vb = Reubo Vehicle Bay, r rt = Jodon Rocket Turret, g rf = Ephrati Refinery (research), b r = Reubo Refinery (ore). The full code→model→faction mapping lives in the official client.


1. Building data model#

1.1 Hard-coded type data (proto/config.proto:284-371, BuildingData)#

Each type entry under building_types (config map key = the type string) has:

Field Meaning
enter_radius L1 (hex) radius around the centre to enter/exit
shape_tiles[] footprint tiles relative to centre (untransformed)
foundation (AllCombatData) combat + regen data while it's a foundation
full_building (AllCombatData) combat + regen data once finished
construction (ConstructionData) foundation cost, full cost, blocks, faction
offered_services (Services) which of the 6 services it provides

1.2 Per-instance state (proto/building.proto:48-120, Building)#

Stored partly in the DB row, partly in the Building proto:

Field Meaning
DB owner owner account name ("" for ANCIENT) (database/building.hpp:41,66)
DB faction immutable instance faction (database/building.hpp:69)
DB centre hex centre coordinate
shape_trafo.rotation_steps 0–5 clockwise 60° rotations (building.proto:32-41)
foundation (bool) true while still a foundation
construction_inventory materials dropped in toward full construction
ongoing_construction ongoing-op ID currently upgrading it (if any)
combat_data derived from type's foundation/full data
config.service_fee_percent owner-set service fee (% of base)
config.dex_fee_bps owner-set DEX fee (basis points)
age_data.founded_height / finished_height block heights

1.3 Shape, rotation, footprint#

GetBuildingShape rotates each shape_tile clockwise by rotation_steps, then offsets by the centre (buildings.cpp:35-53). A worked example from the tests: a checkmark (tiles (0,0),(1,0),(0,1),(0,2)) placed at (-1,5) with rotation_steps = 2 yields the tiles (-1,5),(-1,4),(0,4),(1,3) (buildings_tests.cpp:58-72).

Footprint sizes (number of tiles) vary hugely; see the catalog in §3.


2. Placement rules (founding a building)#

2.1 The fb ("found building") move#

Issued as a character sub-command. The character must be out of any building and not busy, and standing where the foundation will be placed.

[
  {
    "name": "domob",
    "move": {"c": {"id": 1, "fb": {"t": "r cc", "rot": 3}}}
  }
]

fb is an object that must have exactly two members: t (type string) and rot (integer 0–5) (moveprocessor.cpp:1176-1184, 1140-1162). Any extra member, missing member, non-string t, unknown type, or rot outside [0,5] (including a float like 4.0) is rejected (moveprocessor_tests.cpp:1751-1793).

2.2 Validation order (moveprocessor.cpp:1169-1251)#

A foundation is created only if ALL of the following hold:

  1. fb is well-formed (above).
  2. Character is not busy (IsBusy()), e.g. not in an ongoing op (moveprocessor.cpp:1186-1191; _tests.cpp:1795-1806).
  3. Character is not already inside a building (moveprocessor.cpp:1193-1199; _tests.cpp:1808-1819).
  4. The type has a construction block — otherwise "cannot be constructed". itemmaker-style service-only types are rejected (moveprocessor.cpp:1201-1206; _tests.cpp:1821-1830).
  5. If the type has an inferred construction.faction, the character's faction must match it (moveprocessor.cpp:1208-1220; _tests.cpp:1860-1883: a RED character can build r test but not g test).
  6. The character's inventory holds at least the foundation cost (moveprocessor.cpp:1222-1235; _tests.cpp:1832-1842).
  7. CanPlaceBuilding passes for the chosen tiles (moveprocessor.cpp:1241-1248). See §2.3.

The character itself is temporarily removed from the dynamic-obstacle map during the placement check, since they will be inside the foundation anyway (moveprocessor.cpp:1237-1240).

2.3 CanPlaceBuilding — terrain & collision (buildings.cpp:62-102)#

Every footprint tile must satisfy:

  • Passable on the base map (buildings.cpp:71-75; _tests.cpp:141-147).
  • Not in a no-combat / safe zone — you cannot build in neutral no-combat zones or in any faction starter zone (buildings.cpp:76-80; _tests.cpp:149-160).
  • Free of dynamic obstacles — no other building tile and no character vehicle (buildings.cpp:81-85; _tests.cpp:162-166).
  • All tiles in the same region — a building may not straddle two map regions (buildings.cpp:87-99; _tests.cpp:168-176).

2.4 What founding does (moveprocessor.cpp:1639-1669)#

  • Creates a new building (buildings.CreateNew(type, owner, faction)), owner = character's owner, faction = character's faction.
  • Sets foundation = true, applies shape_trafo, sets age_data.founded_height = current height.
  • Subtracts the foundation cost from the character's inventory.
  • Calls UpdateBuildingStats (foundation HP) and immediately puts the character inside the new foundation (EnterBuilding), then registers the building as a dynamic obstacle.

The character ends up inside the foundation so they can immediately drop the remaining construction materials. Founding happens before drop/pickup processing within the same move, so a single move can found + drop (moveprocessor.cpp:1875-1888; _tests.cpp:1917-1940). It also happens before exit, so xb in the same move would leave again (_tests.cpp:1942-1960).


3. Construction (foundation → full building)#

3.1 Lifecycle#

  1. Found a foundation (§2). HP = foundation HP (low). It has no attacks and offers no services yet (services require the full building; see §5).
  2. Deliver materials: a character inside the foundation drops items into the building's construction_inventory (moveprocessor.cpp:1760-1774).
  3. When the construction inventory holds at least the full-building cost, construction auto-starts (MaybeStartBuildingConstruction, buildings.cpp:123-149; triggered after each drop, moveprocessor.cpp:1773).
  4. After construction.blocks blocks, an ongoing op finishes it (ongoings.cpp:113-143).

3.2 Auto-start of construction (buildings.cpp:123-149)#

  • Requires foundation() and a construction block.
  • Does nothing if already constructing (has_ongoing_construction).
  • Compares the full_building cost map against the current construction_inventory; if anything is short, it waits (buildings.cpp:134-137; _tests.cpp:206-214).
  • When satisfied, schedules an ongoing op at current_height + construction.blocks and stores its ID in ongoing_construction (buildings.cpp:139-144; _tests.cpp:227-243).

Note the two-stage cost: the foundation cost (paid from the founder's cargo at placement) is separate from and additional to the full_building cost (dropped into the construction inventory afterward).

3.3 Completion (ongoings.cpp:113-143)#

When the ongoing op fires:

  • The full_building cost is removed from construction_inventory.
  • Any leftover materials in the construction inventory are credited to the owner's account inventory inside the new building (ongoings.cpp:132-135).
  • foundation is cleared, ongoing_construction cleared, age_data.finished_height = current height.
  • UpdateBuildingStats applies the full-building HP/combat.

3.4 Stats derivation (buildings.cpp:151-165)#

UpdateBuildingStats copies foundation.combat_data/regen_data while a foundation, or full_building.* once finished, and sets current HP to max. A foundation r rt therefore has 0 attacks and 100/100 HP; the finished r rt has 1 attack and 1000/1000 HP (buildings_tests.cpp:76-89).

Buildings with no foundation/full_building data (ancients, obelisks, common buildings, cities) get default/empty combat data and effectively 0 max HP — they are never targetable / indestructible in practice (see §7, §8).


4. Catalog of player-buildable buildings#

The 6 buildable classes exist in all three factions with identical stats; only the lore model/skin differs by faction. Costs are in raw item units (the GSP stores quantities ×, e.g. Agarite is mat a). Service column lists offered_services flags. HP is armour / shield. All buildable buildings regenerate 10 HP of shield per block (regeneration_mhp.shield = 10000 milli-HP) and no armour regen unless repaired.

Display names (from the game UI): mat a = Agarite, mat b = Borolium.

4.1 Stats & services#

Type Class enter_radius tiles Foundation HP Full HP Attacks Services
r r/g r/b r Refinery (ore) 8 13/13/9 100k/100k 1M/1M none refining
r rt/g rt/b rt Rocket Turret 6 19 100/100 1k/1k 1 (see §6) none
r rf/g rf/b rf Refinery (research) 7 44/46/39 100k/100k 1M/1M none blueprint_copy, reverse_engineering
r cf/g cf/b cf Construction Facility 9/8/8 50/43/51 100k/100k 1M/1M none item_construction, vehicle_construction
r vb/g vb/b vb Vehicle Bay 8/8/11 11/44/105 100k/100k 1M/1M none armour_repair, vehicle_construction
r cc/g cc/b cc Command Centre 16/10/10 277/87/89 100k/100k 1M/1M none ALL six services

(enter_radius/tiles per faction file; HP/regen from *_*.pb.text; e.g. r_r.pb.text:62-75, r_rt.pb.text:78-103, r_cc.pb.text:859-872.)

The Command Centre offers all six services and is the only buildable building offering the full set. It is also the faction's spawn building for new characters (§9).

4.2 Construction costs#

Foundation cost = paid from founder's cargo at placement; Full cost = dropped into the construction inventory afterward. All construction takes 10 blocks (blocks: 10).

Type Foundation cost Full-building cost
Refinery (ore) r/g/b r 6,400,000 Agarite + 1,600,000 Borolium 128,000,000 Agarite + 32,000,000 Borolium
Rocket Turret r/g/b rt 1,600,000 Agarite + 400,000 Borolium 32,000,000 Agarite + 8,000,000 Borolium
Refinery (research) r/g/b rf 12,800,000 Agarite + 3,200,000 Borolium 256,000,000 Agarite + 64,000,000 Borolium
Construction Facility r/g/b cf 16,000,000 Agarite + 4,000,000 Borolium 320,000,000 Agarite + 80,000,000 Borolium
Vehicle Bay r/g/b vb 25,600,000 Agarite + 6,400,000 Borolium 512,000,000 Agarite + 128,000,000 Borolium
Command Centre r/g/b cc 32,000,000 Agarite + 8,000,000 Borolium 640,000,000 Agarite + 160,000,000 Borolium

(Sources: r_r.pb.text:47-61, r_rt.pb.text:63-77, r_rf.pb.text:141-155, r_cf.pb.text:159-173, r_vb.pb.text:42-56, r_cc.pb.text:844-857; the g_*/b_* files carry identical costs.)

The Rocket Turret is the cheapest and the Command Centre the most expensive.


5. Services offered by buildings#

Six service types exist (config.proto:358-366, BuildingData.Services):

Service flag What it does Cost mechanic
refining Refine raw ores → refined materials per-recipe RefiningData.cost (burnt vCHI)
armour_repair Repair character armour HP armour_repair_cost_millis × HP (params)
reverse_engineering Reverse-engineer artefacts → blueprints RevEngData.cost (burnt)
blueprint_copy Copy a blueprint original bp_copy_cost × complexity (params)
item_construction Build fitments/items from blueprints construction_cost × complexity
vehicle_construction Build vehicles from blueprints same as item construction

A service can only be used inside a building whose type sets that flag; the GSP checks Building(type).offered_services() for each operation (e.g. refining at services.cpp:117-119, armour repair 298, reverse-eng 467, bp copy 627, item/vehicle construction 837). The numerical service costs and block-times themselves are documented in the services/economy doc; this doc covers which buildings expose them and the owner-fee layer.

5.1 Where each service lives (full picture)#

Building refining armour_repair reverse_eng bp_copy item_construction vehicle_construction
cc Command Centre
r Refinery (ore)
rf Refinery (research)
cf Construction Facility
vb Vehicle Bay
rt Rocket Turret (none)
Common c1c11 varies* varies* varies* varies* varies* varies*
Ancient ancient1/2/3 & City ss

* The decorative common buildings DO declare offered_services (and most add armour_repair), e.g. b c1 → armour_repair + refining; g c1 → armour_repair + reverse_engineering + blueprint_copy. They are ancient (no owner, no fee — see §5.2) but, being placed only inside ancient cities, are usable service hubs. See §3.4: they have no HP data → indestructible.

(Common-building service sets, per file: e.g. b_c1.pb.text armour_repair + refining; g_c1.pb.text armour_repair + reverse_engineering + blueprint_copy; r_c1.pb.text armour_repair + vehicle_construction. The full per-file matrix is in the appendix §13.)

5.2 Service fees (owner economics) (services.cpp:985-1016)#

Cost of a service = base cost (burnt) + owner fee.

  • If the operation is performed by a mobile character (not inside a building), fee = 0 (services.cpp:991-997).
  • If the building is ANCIENT, or the user is the owner, fee = 0 (services.cpp:999-1009). Note: an owner uses their own building free even though they would get the fee back, so they can operate on a tight budget.
  • Otherwise: fee = ceil(base * config.service_fee_percent / 100) (services.cpp:1011-1015). service_fee_percent is a percentage of the base cost — e.g. 100 = a 100% surcharge.

Fee payment: the user's account is debited base + fee; base is burnt; fee is credited to the building owner's account (services.cpp:1130-1141). The owner can never be the same as the user when a fee is charged (asserted).

The service-cost JSON exposed to clients per operation is: {"base": <burnt>, "fee": <owner fee>} (services.cpp:1116-1121).

5.3 Faction interaction with services#

There is no owner-faction gate on using a service inside a building. Anyone who is inside may use it. However, the outputs can be faction-gated by the user's own faction:

  • Refining/reverse-engineering only yield outputs valid for the user's faction (services.cpp:558-567).
  • Item/vehicle construction: if the produced item has a faction, it must match the user's faction (services.cpp:854-865).

Entry to the building itself IS faction-gated — see §9.


6. Combat stats & the Rocket Turret#

Only the Rocket Turret (rt) has an offensive attack. All other buildable buildings have empty combat_data (they can be attacked but never shoot).

Rocket Turret full-building attack (r_rt.pb.text:86-97, identical g/b):

Property Value
range 6
area (AoE) 2
damage 3–9
weapon_size 40

A foundation rt has 0 attacks and 100/100 HP; finished it has the attack above and 1000/1000 HP (buildings_tests.cpp:76-89).

All buildable buildings regenerate shield at 10 HP/block (regeneration_mhp.shield = 10000). Armour does not auto-regenerate. Building HP for finished buildings (except the turret) is 1,000,000 armour / 1,000,000 shield, making them very tanky.

Targeting/attack mechanics (who they shoot, how AoE works) are covered in the combat doc; buildings participate via combat_data and are targetable as TYPE_BUILDING.


7. Ancient buildings, obelisks, and common buildings#

7.1 Initial ancient buildings on the map (buildings.cpp:104-121)#

At genesis, InitialiseBuildings walks config.initial_buildings and creates each as ANCIENT, owner = "", with founded_height = finished_height = 0, then UpdateBuildingStats. Because these types lack foundation/full_building data, they get default (effectively 0 max-HP / no-combat) combat data — they are never killed.

The placed initial buildings (proto/roconfig/initialbuildings.pb.text):

Type Centre (x, y) Notes
obelisk1 (-125, 810) neutral landmark, no-combat r=30
obelisk2 (-1301, 902) neutral landmark
obelisk3 (-637, -291) neutral landmark
g cc (-3489, 1823) GREEN spawn (building id 4)
b cc (636, 2446) BLUE spawn (building id 5)
r cc (1919, -2605) RED spawn (building id 6)
g c1g c10, r c1r c11, b c1b c11 many decorative city clusters

The three command centres are placed as ANCIENT at genesis (so the spawn targets exist) — they are not owned by any player even though cc is a player-buildable type. Players can additionally build their own cc.

Building IDs are assigned in file order: obelisk1=1, obelisk2=2, obelisk3=3, g cc=4, b cc=5, r cc=6 — matching params.spawn_areas (params.pb.text:33-47).

The bulk of the file (lines 31–666) is dense clusters of c1c11 common buildings forming the three ancient "cities" near each faction's command centre, each tile-rotated to fit together (initialbuildings.pb.text:131-665).

7.2 Obelisks (obelisk1/2/3.pb.text)#

Huge neutral landmarks. enter_radius 31–35, footprints ~970–1075 tiles. No construction, no combat, no services. Surrounded by 30-tile no-combat zones (safezones.pb.text:26-28).

7.3 ancient1/2/3 and ss cities — defined but unused#

ancient1/2/3.pb.text define large all-service ancient hubs (enter_radius 54/56/58, ~352–378 tiles, all six services, no HP/combat/construction), and r/g/b ss.pb.text define enormous "City" types (enter_radius 150, all six services). Neither appears in initialbuildings.pb.text nor anywhere in the GSP source, so they are not placed in the live game. Treat them as legacy / client-compat definitions.

7.4 Common buildings c1c11#

Decorative ancient city buildings. They declare enter_radius, offered_services, and shape_tiles, but have no construction, foundation, or full_building data — so they cannot be built by players and are indestructible. They DO offer services (mostly armour_repair plus one other), making the ancient cities functioning service hubs with zero owner fee (ANCIENT → fee 0). Full per-file service matrix in §13.


8. Destruction — what happens & what drops#

When a building's HP reaches 0 it is killed via KillProcessor::ProcessBuilding (combat.cpp:1164-1277). Only player-built buildings can ever reach this state (ancients have no combat data).

8.1 Items collected before drop#

A "combined inventory" totalInv is assembled from everything inside (combat.cpp:1177-1241):

  • All account inventories stored in the building (combat.cpp:1179-1183).
  • Every character inside the building is destroyed; their cargo, their vehicle item, and all their fitments are added to totalInv (combat.cpp:1185-1200). (Characters inside a destroyed building die.)
  • Ongoing operations inside: a blueprint-copy returns its original BP type; an item-construction returns its original BP (if any) — both added to totalInv (combat.cpp:1202-1224).
  • DEX open bids: reserved Cubits are refunded to the bidders' accounts (combat.cpp:1226-1234). DEX asks: reserved item quantities are added to totalInv (combat.cpp:1235-1236).
  • If it was still a foundation, its construction_inventory is added (combat.cpp:1240-1241).

8.2 The drop roll (combat.cpp:1245-1271)#

The building is removed as a dynamic obstacle. Then, for each item position in totalInv (iterated in sorted order for determinism), the GSP rolls:

  • 30% chance (BUILDING_INVENTORY_DROP_PERCENT = 30, combat.cpp:43-47) the entire stack of that item drops as ground loot at the building's centre; otherwise the whole stack is destroyed.

So on average ~70% of everything inside a destroyed building is lost forever.

8.3 Cleanup (combat.cpp:1273-1276)#

Building inventories, ongoing ops, and DEX orders for the building are deleted, then the building row itself is deleted.

Contrast with character death: a killed character's cargo always drops, but equipped fitments only drop at a 20% chance (EQUIPPED_FITMENT_DROP_PERCENT = 20, combat.cpp:49-53) and the vehicle is always destroyed.


9. Entering & leaving buildings#

9.1 Entering (eb move)#

[
  {"name": "domob", "move": {"c": {"id": 1, "eb": 100}}}
]

eb sets the character's "intent" to enter building ID 100; eb: null cancels intent (moveprocessor.cpp:662-727, 1502-1508; _tests.cpp:2040-2078). Validation at parse time (moveprocessor.cpp:662-727):

  • Rejected if already in a building (670-677).
  • Building must exist (700-707).
  • Faction gate: anyone may enter ANCIENT buildings, but otherwise a character may only enter a building of its own faction (moveprocessor.cpp:709-720).

The intent is realized later by ProcessEnterBuildings (buildings.cpp:178-233):

  • A character actually enters only if its position is within the building's enter_radius (L1 distance) of the centre (buildings.cpp:215-221; _tests.cpp:327-339 "TooFar"). E.g. for a checkmark (radius 5) a character at distance 5 enters but distance 6 does not (_tests.cpp:388-412).
  • A busy character cannot enter (buildings.cpp:192-197; _tests.cpp:298-311).
  • If the building was destroyed in the meantime, the intent is cleared (buildings.cpp:204-213; _tests.cpp:313-325).

Entering effects (EnterBuilding, buildings.cpp:167-176): the vehicle is removed from the dynamic-obstacle map, building_id is set, the enter-intent is cleared, combat target is cleared, and movement and mining are stopped (_tests.cpp:341-386).

9.2 Leaving (xb move)#

[
  {"name": "domob", "move": {"c": {"id": 1, "xb": {}}}}
]

xb must be an empty object (moveprocessor.cpp:729-744). A busy character cannot exit (746-751). LeaveBuilding (buildings.cpp:235-252) places the character at a random passable, unobstructed tile within enter_radius of the centre, via ChooseSpawnLocation. If the whole radius is blocked it falls outside the radius rather than failing (_tests.cpp:480-491), and many simultaneous exits each get distinct tiles (_tests.cpp:493-517).


10. Owner configuration, transfer, and the update delay#

All owner operations are issued under the top-level b move command (NOT under a character c). b may be a single object or an array of operations (moveprocessor.cpp:343-405).

10.1 Config update (sf service fee, xf DEX fee)#

[
  {
    "name": "andy",
    "move": {"b": [
      {"id": 101, "sf": 50},
      {"id": 102, "xf": 250}
    ]}
  }
]
  • sf = service_fee_percent. Must be an unsigned integer 0 ≤ sf ≤ MAX_SERVICE_FEE_PERCENT = 1000 (moveprocessor.cpp:48, 258-273). Above 1000, negative, float, or string values are rejected (_tests.cpp:3359-3414).
  • xf = dex_fee_bps (basis points). Must be an unsigned integer 0 ≤ xf ≤ MAX_DEX_FEE_BPS = 3000 (moveprocessor.cpp:54, 279-294; _tests.cpp:3416-3471). 3000 bps = 30% cap.
  • Only the owner may update; ancient buildings can never be updated (moveprocessor.cpp:386-401; _tests.cpp:3295-3317).

Updates are not applied immediately. They are scheduled as an ongoing op at current_height + params.building_update_delay (moveprocessor.cpp:1907-1921). Default delay = 120 blocks (params.pb.text:18). When the op fires, the new config is merged into the existing config so unset fields are preserved (ongoings.cpp:206-217). In the JSON state this pending op shows as {"operation": "config", "newconfig": {...}} (gamestatejson.cpp:558-560).

Multiple config updates to the same building in one move each create their own delayed op (_tests.cpp:3319-3357).

10.2 Transfer (send)#

[
  {"name": "andy", "move": {"b": {"id": 101, "send": "domob"}}}
]

send transfers ownership (moveprocessor.cpp:298-324, 1922-1930):

  • Target account must exist and be initialised (moveprocessor.cpp:307-314; _tests.cpp:3473-3496 rejects uninit/nonexistent).
  • Target must be the same faction as the building (moveprocessor.cpp:315-321; transfer to a BLUE account of a RED building is rejected).
  • Effect is immediate (no delay): b.SetOwner(newOwner) (moveprocessor.cpp:1929).
  • Only the owner may issue it (the surrounding TryBuildingUpdates owner check applies). A send and an sf/xf can be combined in one b entry; the config update schedules first, then the transfer applies — so the schedule is attributed to the old owner and the building ends up with the new owner (moveprocessor.cpp:327-341; _tests.cpp:3498-3515).

11. Game-state JSON (what the client reads)#

GameStateJson::Convert<Building> (gamestatejson.cpp:407-468) emits per building:

{
  "id": 1234,
  "type": "r cc",
  "foundation": true,            // present only while a foundation
  "faction": "r",                // "r"|"g"|"b"|"a" (ancient)
  "owner": "domob",              // omitted for ancient
  "centre": {"x": 1919, "y": -2605},
  "rotationsteps": 0,
  "config": {"servicefee": 50, "dexfee": 2.5},  // dexfee = bps/100 (a percent)
  "tiles": [{"x":..,"y":..}, ...],              // transformed footprint
  "combat": { /* HP, attacks, regen — see combat doc */ },
  // foundation only:
  "construction": {"ongoing": 9001, "inventory": {"mat a": 1000}},
  // full building only:
  "inventories": {"domob": {"mat a": 5}},       // per-account stored items
  "reserved": {"mat a": 3},                      // items reserved by DEX asks
  "orderbook": { /* DEX bids/asks in this building */ },
  // always:
  "age": {"founded": 0, "finished": 12345}       // "finished" omitted while foundation
}

config.servicefee is the raw percent; config.dexfee is reported as a percent (dex_fee_bps / 100.0) (gamestatejson.cpp:330-336).

The full building list is exposed under the top-level buildings array of game state (gamestatejson.cpp:746-794).


12. Starter cities & spawning (geography)#

Each faction has a command centre at genesis (ANCIENT), a 300-tile starter safe zone around it, and a surrounding decorative ancient "city" of common buildings.

Faction Command Centre centre Spawn building id Starter zone centre / radius
RED (Jodon) (1919, -2605) 6 (1960, -2601), r=300 (safezones.pb.text:3-8)
GREEN (Ephrati) (-3489, 1823) 4 (-3472, 1824), r=300 (safezones.pb.text:10-15)
BLUE (Reubo) (636, 2446) 5 (547, 2497), r=300 (safezones.pb.text:17-22)

New characters spawn inside their faction's command centre (spawn.cpp:117-152): they are created with a starter vehicle — rv st = Raider (RED), gv st = Scarab (GREEN), bv st = Barracuda (BLUE) — one lf gun = Light Rail Gun fitment, and building_id set to the faction's spawn building (params.spawn_areas, params.pb.text:33-47). Display names are the ones shown in the game UI.

Within a starter safe zone (a faction zone), no combat occurs and no new buildings may be founded (safe-zone rule, buildings.cpp:76-80; _tests.cpp:149-160 confirms StarterFor((-2042,100)) == RED).

Mainnet vs testnet/regtest. Building type definitions, services, HP, costs, and the building_update_delay/fee caps are shared. The mainnet safe zones, spawn areas, prizes, and params live in proto/roconfig/{safezones,params,...}.pb.text. The regtest config (config.proto:646-660, testnet_merge/regtest_merge) merges in alternative test_safezones.pb.text/test_params.pb.text and the buildings/test.pb.text types (checkmark, huesli, itemmaker, carmaker, r/g/b test) used only by tests. Notably, regtest replaces (not concatenates) the safe-zones and prizes lists. god_mode is true in the bundled params (params.pb.text:31) — it enables admin teleport/mint commands and is intended to be disabled on mainnet.


13. Appendix — full service matrix of common (ancient) buildings#

All offer armour_repair plus the listed extra(s). enter_radius / footprint tiles also shown. Sources: {r,g,b}_c*.pb.text.

Type enter_radius tiles Extra services (besides armour_repair)
r c1 12 164 vehicle_construction
r c2 13 174 refining
r c3 10 104 item_construction
r c4 8 62 reverse_engineering, blueprint_copy
r c5 9 64 vehicle_construction
r c6 8 43 refining
r c7 10 107 item_construction
r c8 9 72 reverse_engineering, blueprint_copy
r c9 8 50 vehicle_construction
r c10 7 29 refining
r c11 8 49 item_construction
g c1 14 255 reverse_engineering, blueprint_copy
g c2 12 140 item_construction
g c3 12 134 vehicle_construction
g c4 7 35 refining
g c5 8 49 reverse_engineering, blueprint_copy
g c6 8 43 item_construction
g c7 11 99 vehicle_construction
g c8 9 71 refining
g c9 10 81 reverse_engineering, blueprint_copy
g c10 10 84 item_construction
b c1 10 111 refining
b c2 12 126 reverse_engineering, blueprint_copy
b c3 10 77 item_construction
b c4 10 90 vehicle_construction
b c5 12 139 refining
b c6 11 120 reverse_engineering, blueprint_copy
b c7 8 53 item_construction
b c8 11 121 vehicle_construction
b c9 9 64 refining
b c10 9 62 reverse_engineering, blueprint_copy
b c11 8 49 item_construction

(Green has only c1c10; Red and Blue have c1c11.)


Open questions#

  1. ancient1/2/3 and ss (City) types are defined but never instantiated. They have full all-service configs and large footprints but appear in neither initialbuildings.pb.text nor any GSP source path. It is unclear whether they are dead config kept for historical reasons, intended for a future admin/god-mode placement, or were placed via a mechanism not present in the read sources. (The official client even notes that cities are "manually recreated from individual buildings".)
  2. Genesis command centres are ANCIENT but cc is a player-buildable type. The three spawn CCs are created with faction ANCIENT / no owner, so they are indestructible (no combat data) and free of fees. A player-built cc would instead have the full-building 1M/1M HP and owner fees. The exact intended long-term behavior if a faction's spawn CC were ever absent (it can't be, as ancient) is not exercised in the read code.
  3. sf/ep/et client model codes map to client model assets but have no GSP type. They render nothing in the live game; presumably future/cut content.