Skip to content

Vault Tileset Override — Design Spec

Date: 2026-07-09 · Status: approved (per-role fallback, BiomeDef-authored)

Goal

Let a biome give its vault room custom floor/wall art: a vaultTileSet on BiomeDef that overrides the biome tileset inside the vault's room box, with a two-level fallback — no asset assigned → the vault renders with the biome tileset exactly as today; an assigned set whose grounds or walls array is empty → that role falls back to the biome art while the other role still overrides.

Components

1. BiomeDef (Assets/Scripts/Config/BiomeDef.cs)

New serialized field next to the existing art fields (tileSet / outerTileSet):

[Tooltip("Vault-room art override (walls ring + interior floor + gate tile). Null → the vault " +
         "uses this biome's tileSet. Per-role fallback: an empty grounds/walls array keeps the " +
         "biome art for that role (unlike a theme's whole-set override).")]
public TileSet vaultTileSet;

No HasAllArt requirement — partial vault sets are the point.

2. TileSet (Assets/Scripts/World/TileSet.cs)

Two public helpers beside HasAllArt (the private Count already exists):

/// <summary>Role-level presence — used by partial overrides (the vault set) that fall back per role.</summary>
public bool HasGrounds => Count(grounds) > 0;
public bool HasWalls => Count(walls) > 0;

3. MapGenerator.ResolveTileSets (Assets/Scripts/World/MapGenerator.cs)

After the themed-zone stamping loop, stamp the vault box per role:

  • Guard: m.Vault != null and a resolved vault set is non-null; skip entirely otherwise.
  • Walk m.Vault.RoomTileBox (it already includes the wall ring, interior floor, and gate tile), clamped to map bounds like the zone loop.
  • Per tile: role = m.Get(tx, ty) == TileType.Wall → wall, else floor (the gate tile is floor → it reads as vault flooring; bushes never occur inside the box — clutter placement excludes the vault room).
  • Assign _tileSetAt[idx] = vaultSet only when the set has art for that tile's role (HasWalls / HasGrounds) — otherwise the tile keeps whatever it already has (biome default; the vault avoids zones so themed overlap is theoretical, but stamping after zones makes the priority explicit: vault > theme > biome).

Consequences that need no extra code: the material cache and variant-adjacency logic are already keyed per tile-set; tint (wallTint/floorTint) and wallHeight follow whichever set a tile actually uses, so an overridden wall renders with the vault set's tint/height while a fallen-back wall keeps the biome's.

4. Plumbing

  • Raid path: MapGenerator.Generate already receives the BiomeDef (it reads biome.outerTileSet there) — capture biome.vaultTileSet into a private _vaultTileSet alongside _outerTileSet.
  • Tutorial path: RaidBootstrap currently sets map.tileSet = _biomes.Biome(0).tileSet before BuildTutorialMap; it likewise passes Biome(0).vaultTileSet (same public-field or setter style as tileSet). The tutorial vault records MapData.Vault the same way, so ResolveTileSets covers it with no further work. _vaultTileSet must be cleared or re-assigned on every build so a re-roll never leaks the previous run's set.

Out of scope

  • Per-floor or per-theme vault sets (one per biome is the ask).
  • Bush role in the vault set (unused; ignored if authored).
  • Any authoring of actual vault art assets — this is the mechanism only.
  • MapData, pathing, fog, minimap, material/variant systems — untouched.

Verification (no test suite — editor runs)

  1. Compile clean (Unity MCP console).
  2. Assign a visually distinct test TileSet as vaultTileSet on a biome → re-roll → vault room (walls + interior + gate tile) renders the override.
  3. Empty the test set's walls array → walls render biome art, floor stays overridden (and vice versa for grounds).
  4. Unassign vaultTileSet → vault renders exactly as before the change.
  5. Tutorial stage (fresh save) → tutorial vault honors the same override.