Building Types

Buildings provide interactive services and content within locations. Each building type offers specific functionality, from commerce and healing to quest distribution and cultivation.

Basic Buildings

Healer

Provides healing services to restore health and remove injuries:

{
  kind: 'healer',
  condition?: 'realm >= meridianOpening',  // Optional availability
  disabled?: 'injured == 0'  // Optional disable condition
}

Cultivation Chamber

Allows meditation and qi cultivation:

{
  kind: 'cultivation'
}

Manual Pavilion

Access to combat technique manuals:

{
  kind: 'manual'
}

Crafting (Furnace Pagoda)

Alchemy and item crafting:

{
  kind: 'crafting'
}

Treasure Vault

Banking and storage services:

{
  kind: 'vault'
}

Material Compendium

Encyclopedia of crafting materials:

{
  kind: 'compendium'
}

Mystical Region

Portal to special cultivation areas:

{
  kind: 'mysticalRegion'
}

Expedition

Portal to expedition dungeons. Expedition buildings require a name matching an existing expedition tile pool (registered by the base game or via modAPI.actions.addExpeditionTiles).

{
  kind: 'expedition';
  name: string;              // Expedition identifier (e.g. 'Tai Kong')
  displayName?: Translatable; // Optional custom display name
  teamCount: number;         // Number of team members required
  realm: Realm;              // Realm tier for the expedition
}

Example:

{
  kind: 'expedition',
  name: 'Tai Kong',       // Expedition identifier - must match the key used in addExpeditionTiles
  displayName?: 'Tai Kong Expedition',
  teamCount: 3,           // Number of team member slots
  realm: 'qiCondensation' // Minimum realm required to enter
}

The name field is the expedition identifier. It must match the expeditionName passed to api.actions.addExpeditionTiles(expeditionName, tiles) so that the tile pool is correctly associated with this building. See Expedition Tiles below for how to register tiles for a custom expedition.

Training Ground

Combat training and sparring:

{
  kind: 'trainingGround'
}

Research (Vault of Infinite Reflections)

Research and experimentation facility:

{
  kind: 'research'
}

Reforge Workshop

Item reforging and enhancement:

{
  kind: 'reforge'
}

Furnace of Ten Thousand Flames

Advanced alchemy furnace for high-tier crafting:

{
  kind: 'tenThousandFlames'
}

Commerce Buildings

Market

General marketplace with realm-specific inventory:

{
  kind: 'market',
  itemPool: {
    bodyForging: [
      { name: 'Small Claw', stacks: 5 },
      { name: 'Healing Pill I', stacks: 3 },
      { name: 'Speed Room I', stacks: 1 }
    ],
    meridianOpening: [...],
    // ...other realms
  },
  reputationPool?: {  // Optional reputation items
    bodyForging: [
      {
        name: 'Spirit Core I',
        stacks: 1,
        reputation: 'respected',  // Required reputation
        valueModifier: 15         // Price multiplier
      }
    ]
  },
  costMultiplier: 1.5,   // Base price multiplier
  refreshMonths: 3        // Inventory refresh period
}

Favour Exchange

Special shop using favour currency:

{
  kind: 'favourExchange',
  itemPool: { ... },      // Same as market
  costMultiplier: 2.0,
  refreshMonths: 1
}

Enchantment Shop

Shop for purchasing item enchantments:

{
  kind: 'enchantmentShop',
  costMultiplier: 1.5,   // Base price multiplier
  refreshMonths: 1,       // Inventory refresh period
  stockCount: 6           // Number of enchantments available at a time
}

Mission Buildings

Mission Hall

Sect missions with rewards:

{
  kind: 'mission'
}

Missions defined at location level:

missions: [
  {
    realm: 'bodyForging',
    rarity: 'mundane',
    quest: 'ratascar_culling',
    condition: '1'
  }
]

Crafting Hall

Crafting-focused missions:

{
  kind: 'craftingHall'
}

Crafting missions defined at location level:

crafting: [
  {
    realm: 'meridianOpening',
    rarity: 'qitouched',
    quest: 'pill_delivery',
    condition: 'craftingSkill >= 50'
  }
]

Request Board

Player-requested tasks:

{
  kind: 'requestBoard',
  requests: {
    bodyForging: [
      {
        quest: 'herb_collection',
        condition: '1',
        rarity: 'mundane'
      }
    ],
    meridianOpening: [...],
    // ...other realms
  }
}

Resource Buildings

Herb Field

Herb gathering location:

{
  kind: 'herbField',
  condition?: 'farmingUnlocked == 1'
}

Yinying Mine

Mining for ores and gems:

{
  kind: 'mine',
  condition?: 'miningUnlocked == 1'
}

Special Buildings

Recipe Library

Access to crafting recipes:

{
  kind: 'recipe',
  recipePool: {
    bodyForging: [
      'recuperation_pill_recipe',
      'iron_skin_pill_recipe',
      'clothing_blank_recipe'
    ],
    meridianOpening: [...],
    // ...other realms
  }
}

Library

Books and lore:

{
  kind: 'library',
  title: 'Ancient Archives',
  categories: [
    {
      name: 'History',
      condition: '1',
      books: [
        {
          title: 'Rise of the Nine Mountains',
          author: 'Elder Shou',
          condition?: 'historyInterest == 1',
          contents: 'Long ago, when the heavens...'
        }
      ]
    },
    {
      name: 'Cultivation Theory',
      condition: 'realm >= meridianOpening',
      books: [...]
    }
  ]
}

House

Player housing:

{
  kind: 'house',
  houseDef: {
    name: 'Heaven-Touched House',
    description: 'Your rebuilt childhood home...',
    background: homeImage,
    screenEffect: 'dust',
    qiDensity: 1000,
    fixedRooms: [],
    freeRooms: 3,
    transportSeal: liangTiaoSeal
  },
  unlockCondition: 'houseRepaired == 1',
  condition: 'houseRepaired == 1'
}

Compression Altar

Core compression service. Grants a temporary buff on use and a permanent breakthroughReward on the first compression at each altar.

{
  kind: 'altar',
  buff: {
    name: 'Meditative Surge',
    description: 'Your core has been compressed...',
    canStack: true,
    stats: {
      power: {
        value: 0.2,
        stat: 'power',
        scaling: 'stacks',
      },
    },
    // ...other buff properties
  },
  // Optional: permanent stat rewards granted once per altar on first compression.
  // These rewards persist through Core Formation breakthrough.
  breakthroughReward?: {
    // Combat stat increments — flat values or percentage of a stat.
    // Example: { value: 0.03, stat: 'power' } = +3% of current power.
    combatStats?: Partial<{ [key in CombatStatistic]: Scaling }>;
    // Crafting stat increments — e.g. poolCostPercentage reduces qi costs.
    craftingStats?: Partial<{ [key in CraftingStatistic]: Scaling }>;
  };
}

breakthroughReward is optional. If omitted, compressing at the altar grants no permanent bonus. Each unique altar (identified by location name or house name) can grant its breakthroughReward once per playthrough. The same altar visited again provides only the temporary buff.

Available CombatStatistic keys include power, protection, critchance, critmult, speed, dr (damage resistance), accuracy, evasion, maxhp, barrierMitigation, barrierStrength, startingBarrier, weakness, armour, and block. Percentage scaling (e.g. +10% of current power) uses { value: 0.1, stat: 'power' }. Flat values use { value: 5, stat: undefined }.

Available CraftingStatistic keys include control, 流派强度 (technique intensity), critchance, critmult, successChanceBonus, poolCostPercentage, qualityBonus, and speed. poolCostPercentage with value 0.95 reduces qi pool costs to 95% of normal.

Guild

Guild headquarters:

{
  kind: 'guild',
  guild: 'Merchant Alliance',
  position: 'topleft',
  condition?: 'guildUnlocked == 1',
  /** Token currency for this guild's shop. When set, the shop uses tokens instead
   *  of spirit stones and every rankShop item must declare a `tokenCost`. */
  token?: Item,
}

Items sold in a token-based guild’s rank shop declare a fixed token price:

{
  kind: 'rankShop',
  tokenCost: 3, // Fixed price in the guild's token currency
  // ...
}

Important: When a guild declares token, every item in its rankShop must declare tokenCost. Items without it would be charged in spirit stones instead.

Custom Building

Fully customizable building with event steps:

{
  kind: 'custom',
  name: 'Mysterious Shop',
  icon: shopIcon,
  position: 'middleright',  // Screen position
  condition: 'mysteryUnlocked == 1',
  eventSteps: [
    {
      kind: 'text',
      text: 'You enter the mysterious shop...'
    },
    {
      kind: 'choice',
      choices: [
        {
          text: 'Browse wares',
          children: [...]
        },
        {
          text: 'Leave',
          children: [
            { kind: 'exit' }
          ]
        }
      ]
    }
  ]
}

Position options for custom buildings:

  • 'top', 'topleft', 'topright'
  • 'belowtop', 'belowtopleft', 'belowtopright'
  • 'middleleft', 'middle', 'middleright'
  • 'bottom', 'bottomleft', 'bottomright'

Mod-Specific Buildings

Mod Building

A custom building that navigates to a registered mod screen. Use modBuilding alongside api.addScreen() to integrate fully custom UI into a location.

{
  kind: 'modBuilding',
  name: 'Mysterious Device',          // Internal name (used as icon seed)
  displayName?: 'Mysterious Device',  // Optional display name (supports translation)
  icon: myCustomIcon,                 // Building icon image
  screen: 'myModScreen',              // Key of screen registered via api.addScreen()
  position: 'middleleft',             // Position on the location screen
  condition?: 'deviceUnlocked == 1',  // Optional: when to show the building
  disabled?: 'deviceBusy == 1'        // Optional: when to disable the button
}

The screen field must match the key used when registering the screen with api.addScreen(). See Adding Screens for how to create and register mod screens.

// Register the screen
api.addScreen({
  key: 'myModScreen',
  component: MyModScreenComponent,
});

// Add the building to a location
window.modAPI.actions.addBuildings('Liang Tiao Village', [
  {
    kind: 'modBuilding',
    name: 'Ancient Device',
    icon: deviceIcon,
    screen: 'myModScreen',
    position: 'top',
    condition: '1',
  }
]);

Building Properties

Common Properties

All buildings support these optional fields:

{
  kind: BuildingType,      // Required building type
  condition?: string,       // When building is available
  disabled?: string,        // When building is disabled
  offset?: {               // Position adjustment
    x: number,
    y: number
  }
}

Conditional Availability

Control when buildings appear:

{
  kind: 'market',
  condition: 'marketBuilt == 1 && realm >= meridianOpening',
  // ...other properties
}

Disabled State

Temporarily disable buildings:

{
  kind: 'healer',
  disabled: 'injured == 0',  // Disabled when not injured
}

Complete Example

export const myLocation: GameLocation = {
  // ...basic properties

  buildings: [
    // Basic services
    { kind: 'healer' },
    { kind: 'crafting' },

    // Market with reputation items
    {
      kind: 'market',
      itemPool: {
        bodyForging: [
          { name: 'Healing Pill I', stacks: 5 },
          { name: 'Small Claw', stacks: 10 }
        ]
      },
      reputationPool: {
        bodyForging: [
          {
            name: 'Rare Manual',
            stacks: 1,
            reputation: 'exalted',
            valueModifier: 10
          }
        ]
      },
      costMultiplier: 1.8,
      refreshMonths: 2
    },

    // Custom event building
    {
      kind: 'custom',
      name: 'Elder\'s Residence',
      icon: elderIcon,
      position: 'top',
      condition: 'elderQuestComplete == 1',
      eventSteps: [
        {
          kind: 'speech',
          character: 'Village Elder',
          text: 'Welcome back, young cultivator...'
        },
        // ...more events
      ]
    },

    // Conditional library
    {
      kind: 'library',
      condition: 'libraryUnlocked == 1',
      title: 'Village Archives',
      categories: [
        {
          name: 'Local History',
          condition: '1',
          books: [...]
        }
      ]
    },

    // Mod screen building
    {
      kind: 'modBuilding',
      name: 'Alchemist Workshop',
      icon: workshopIcon,
      screen: 'myAlchemistScreen',
      position: 'middleright',
      condition: 'workshopBuilt == 1',
    }
  ]
};

Expedition Tiles

Expeditions use a tile-based dungeon generation system. Each tile has a kind (entrance, exit, combat, treasure, etc.) and defines connections to neighbouring tiles.

Tiles are registered via api.actions.addExpeditionTiles(expeditionName, tiles) and are keyed by the same expedition identifier used in the expedition building’s name field. An expedition building without any tiles registered will use the default game tiles.

Reading existing tiles:

// Inspect the tile pool for an existing expedition
const tilePool = window.modAPI.gameData.expeditionTiles['Tai Kong'];
const treasureTiles = tilePool.filter((t) => t.kind === 'treasure');

Registering tiles for a custom expedition:

// Register a new expedition with a custom treasure tile
window.modAPI.actions.addExpeditionTiles('Frozen Reach', [
  {
    kind: 'treasure',
    name: 'Glacial Cache',
    icon: 'mod://icons/ice.png',
    bg: 'mod://backgrounds/iceBG.png',
    description: 'A cache pulsing with cold qi.',
    rarity: 'resplendent',
    intro: [{ kind: 'text', text: 'You uncover a cache of frozen treasures.' }],
    expeditionTiles: [],
    edges: { left: [], right: [], top: [], bottom: [] },
    tileConnections: [],
    edgeConnections: [],
  },
]);

Tile Kinds

All tile types share these base fields:

interface BaseTile {
  name: string;              // Display name
  icon: string;              // Icon path (use 'mod://' for mod assets)
  bg: string;               // Background image path
  description: Translatable; // Shown when the tile is revealed
  rarity: Rarity;            // 'mundane' | 'qitouched' | 'empowered' | 'resplendent' | 'incandescent' | 'transcendent'
  intro: EventStep[];        // Event steps shown when entering this tile
  // Tile graph fields (required for generation)
  expeditionTiles: ExpeditionTilePoint[];  // Named points inside this tile
  edges: Record<ExpeditionDirection, ExpeditionTilePoint[]>;  // Connections per direction
  tileConnections: { src: string; dst: string }[];           // Named point links
  edgeConnections: { tile: string; edge: string; direction: ExpeditionDirection }[];
}

entrance - Starting tile. Exactly one per expedition.

{ kind: 'entrance', /* ...BaseTile */ }

exit - Goal tile. Reaching this tile completes the expedition.

{ kind: 'exit', /* ...BaseTile */ }

extract - Grants extraction rewards (materials, items).

{ kind: 'extract', extractCount: 3, /* ...BaseTile */ }

combat - Triggers a combat encounter.

{
  kind: 'combat',
  modifier?: number,       // Difficulty multiplier (default 1)
  enemyCount?: number,    // Number of enemies spawned
  items?: { item: ItemDesc; count: number }[],  // Guaranteed drops
  /* ...BaseTile */
}

rest - Restores team health and removes debuffs.

{ kind: 'rest', baseRestore: 50, /* ...BaseTile */ }

treasure - Grants treasure room loot.

{ kind: 'treasure', /* ...BaseTile */ }

boss - Triggers a boss fight with scaled rewards.

{
  kind: 'boss',
  modifier?: number,            // Difficulty multiplier
  items?: { item: ItemDesc; count: number }[],  // Guaranteed drops
  /* ...BaseTile */
}

buff - Applies a positive buff to the team.

{ kind: 'buff', /* ...BaseTile */ }

debuff - Applies a negative debuff to the team.

{ kind: 'debuff', /* ...BaseTile */ }

challenge - High-difficulty combat with extra rewards.

{
  kind: 'challenge',
  modifier?: number,
  items?: { item: ItemDesc; count: number }[],
  /* ...BaseTile */
}

puzzle - A puzzle encounter, optionally with enemies.

{ kind: 'puzzle', enemies?: boolean, /* ...BaseTile */ }

boonBane - Random beneficial or harmful effect.

{ kind: 'boonBane', /* ...BaseTile */ }