# CAIME, the guide: creating and editing a Total War: Warhammer III campaign map

> CAIME (Campaign AI Map Editor), the Campaign Map Toolkit's editor, builds the logical half of a Total War campaign map: regions, ground types, climates, roads, rivers, settlement slots. This guide starts from scratch: what the tool does, its window, every layer and every rule, the exports, the command line, and the pitfalls that cost us hours while porting The Season of Revelation's map from Warhammer I to Warhammer III.

Page: https://bretonia.dev/atelier/en/caime/ · Atlas of Bretonnia, modders' workshop · updated on 2026-09-25. Plain-text version, for readers and AIs; the diagrams are described in words. Reviewed on 25 September 2026, update 9.0. Written against its sources, CAIME 1.0.1's code and documentation, the Assembly Kit on patch 8.1; what 9.0 changed on our project has been added, the rest has not been rechecked point by point.

## What CAIME does

> **Where to start**: **New to this**: read "What CAIME does", "The words of the trade" and "From database to game", then follow "Building a new map, step by step" with a small test map (200 × 150 hexes, three regions). **Porting a map** from another game: go to "Porting a map from another Total War game". **You are an AI**: the section "For an AI reading this page" gathers the checkable rules.

A Total War campaign map has **two halves** describing the same land. The **logical half** lives on a grid of hexagons ("hexes"): ground type, region, climate, rivers, roads, beaches, bridges, settlement slots, impassable areas. It is what the game computes: who owns what, who can go where, and at what cost. The **visual half** is relief, textures, vegetation, water and lighting: what the player sees.

*Diagram: The logical half: hexes coloured by ground type, region borders, a road, a river and four settlement slots.*

CAIME handles the logical half. Think of it as a "Photoshop for data": pick a layer, a value (a *swatch*), a tool, and paint hexes. Then the **Process** menu "develops" the layers into files the game reads: `map_data.esf`, the movement data (pathfinding), the borders (`borders.pbd`), `dynamic_resources.esf`, the lookup images and the minimap (*Lookup and Minimap images* menu; for Warhammer III, a single image, `<campaign>_lookup.bmp`). As far as we know, no other public tool produces `map_data.esf`, the pathfinding, `borders.pbd` or `dynamic_resources.esf`; the images, however, can be made otherwise (we remade our minimap by script).

Games supported, according to its documentation: Rome II, Attila, Thrones of Britannia, Warhammer I to III, Three Kingdoms, Troy, Pharaoh and Pharaoh Dynasties. The v1.0.0 notes, however, call Pharaoh (2023) "currently unsupported", and the repository README does not list it. Not Shogun 2.

## The words of the trade

The whole guide uses these words; they are explained once and for all.

| Word | What it means |
|---|---|
| Assembly Kit | Creative Assembly's free tooling, one per game (Steam → Library → Tools). `binaries` = its programs; `raw_data` = the sources (XML tables, CA's maps); `working_data` = what its tools produce |
| Dave, Tweak, Terry, BOB | the Assembly Kit's tools: Dave edits tables, Tweak is the editor of which Terry (3D terrain) is a mode, BOB builds and packs. See [the Terry guide](https://bretonia.dev/atelier/en/terry/) and [the BOB guide](https://bretonia.dev/atelier/en/bob/) |
| RPFM | Rusted PackFile Manager, the community tool that opens and builds packs: [the RPFM guide](https://bretonia.dev/atelier/en/rpfm/) |
| Pack | a `.pack` archive the game reads; a mod is a pack |
| Table, key | a table of the game's database; each row has a unique key (`regions`, `campaigns`…) |
| ESF | a Creative Assembly binary format (`map_data.esf`, `startpos.esf`); the acronym is undocumented |
| Hex | one cell of the grid, flat-topped; odd columns shifted up; row 0 at the bottom |
| Layer | one kind of data, one value per hex (regions, ground, roads…) |
| Swatch | a value you paint: a ground type, a region, a climate… |
| `map.hex` | a map's CAIME project: all its layers |
| `.hex_layer` | a single layer, exported or to import |
| Process, export | turning the layers into game files (Process menu) |
| Pathfinding | the movement computation: who can go where, at what cost |
| Lookup | an image where each region has its RGB colour; the game reads which region lies under a point |
| Logger | CAIME's message window (Ctrl+L) |
| Slot, sprawl | a town's place on the grid; the town's footprint around it |
| Campaign playable area | the map's row in `campaign_map_playable_areas`: camera limits, minimap files |
| `is_sea` | the `regions` column that says whether a region is a sea |
| *bridge-cliff* | the land hex touching a bridge; CAIME works it out itself: neither a layer nor a ground type, nothing to paint |
| Cliff | for CAIME, any land hex touching the sea that is not a beach; it works it out itself |
| Hazard | impassable, rivers and the whole coast (beach or "cliff"): what a town's sprawl must either touch or keep at least 3 hexes away |
| Province, attrition | a group of regions; armies' wear on a terrain |
| Edge mask | six bits per hex telling which neighbours a road, river or border leads to |
| Startpos | `startpos.esf`, a campaign's starting state, generated by the game; outside CAIME: [the tools](https://bretonia.dev/atelier/en/tools/) |

*Diagram: The words on the map: an annotated map extract.*

1. **Hex**: a flat-topped cell; odd columns are shifted up; cell (0, 0) is at the bottom left.
2. **Sea region**: the sea is a region like any other, with is_sea = 1 in the regions table.
3. **Region and border**: every hex has its region; the Region Borders layer draws the border (Auto-generate).
4. **Cliff**: a land hex touching the sea that is not a beach; CAIME works it out. The coast counts, with rivers and impassable, as a hazard.
5. **Beach**: painted (Beaches), on coastal land only: the landings.
6. **Bridge**: painted (Bridges) on a sea hex, from one shore to the other; the road stops at both shores.
7. **bridge-cliff**: every land hex touching the bridge (hatched); CAIME works it out: nothing to paint.
8. **Slot**: the town: a 19-hex disk; for a port, 16 main hexes (brown line) and 3 Port hexes (blue line), one of them at sea.
9. **Sprawl**: the town's footprint, in ochre: the 19 hexes.
10. **Edge mask**: six bits per road, river or border hex: the sides towards its neighbours; the gold-ringed hex, magnified on the right, has bits 0 (north) and 3 (south).

A map extract drawn for the example, with the guide's words laid on it: the grid, the regions, the coast, a bridge, a port town, a road.

## From database to game: the full chain

CAIME is only one link. Here is the whole path of a new map, at a glance. Two tracks move forward at the same time: CAIME for the logical half, Terry and BOB for the visual half. They meet in the mod's pack; the game then generates turn 0 (the startpos) with that pack loaded (for us, with a second pack, the start-table one: [the tools guide](https://bretonia.dev/atelier/en/tools/)), and the pack is rebuilt with the startpos.

*Diagram: The road map: the database, CAIME (paint, validate, export), Terry and BOB for the terrain, RPFM building the pack, the game generating turn 0, RPFM putting it back in, then testing in game, and repeat.*

In the diagram: 1 · the logical half · The database · declare map, regions, campaign · `regions` · `campaigns` · CAIME · paint the layers · `map.hex` · `tile_map.png` · CAIME · validate (11 checks) · saved · Tweak and Terry closed · project in raw_data · CAIME · export (Process) · `map_data.esf` · `pathfinding.ppd` · `borders.pbd` · `<campaign>_lookup.bmp` · 2 · the visual half · Terry · relief, textures, trees, water · `<map>.terry` · `tile_map.png ← CAIME` · BOB · a run: the terrain · `full_height_map.dds` · `tile_list.bin` · new map: BOB runs only 6 of its 15 actions · 3 · together · RPFM · build the pack: exports, terrain, tables · `my_mod.pack` · The game · generate turn 0 (two packs) · `startpos.esf` · `hlp_data.esf` · `spd_data.esf` · RPFM · put turn 0 back in the pack · `my_mod.pack` · In game · test, read the logs · fix and repeat: export again, then a new startpos

The road map. On top, CAIME builds the logical half: paint, validate, then export, once the project is saved, Tweak and Terry are closed and the project sits in raw_data. Below, meanwhile, Terry and BOB build the visual half, from the database and the tile map CAIME exports; for a new map, BOB runs only 6 of its 15 actions. RPFM builds the mod's pack; the game generates turn 0 with it and the start-table pack, then RPFM puts turn 0 back into it. Under each step, the files it produces. Every change means exporting again, then a new startpos.

And each step in detail, under the road map's numbers, with what it produces:

1. **I · The database**: In the Assembly Kit (Dave, or the XML files by script): the map, its regions, its provinces, the campaign that uses it. (`regions`, `campaigns`, `campaign_map_playable_areas`…)
2. **II–III · CAIME, the layers**: Layers painted or imported, then validated. (`map.hex`)
3. **IV · CAIME, the exports**: Process: what the game reads to move, draw borders and colour the map. And, through Tools → Export → Baseline Tilemap image, the tile map for Terry. (`map_data.esf`, `pathfinding.ppd`, `display\borders\borders.pbd`, `<campaign>_lookup.bmp`, `tile_map.png`)
4. **V–VI · Terry and BOB, meanwhile**: Relief, textures, trees, coasts and water: the terrain the game reads. (`full_height_map.dds`, `tile_list.bin`, `global_props.bin`…)
5. **VII · The pack**: RPFM gathers the exports, terrain, tables and scripts into the mod's `.pack`: the startpos generation needs this pack. (`my_mod.pack`)
6. **VIII–IX · The startpos, then the rebuilt pack**: The game generates turn 0 with the mod's pack loaded (for us, with the start-table pack as well); for a new map, the AI data too. The pack is then rebuilt with these files: in `data`, the pack wins over loose files. Redo it after every export and every minimap change. (`startpos.esf`, `hlp_data.esf`, `spd_data.esf`)
7. **X · In game**: Start a game, read the logs, fix, repeat.

## Before you start: rights and the team's rules

- **CAIME's code** is under a **non-commercial** licence: modifications allowed, no commercial use, share-alike with public source code if you redistribute, copyright notice kept.
- **The files CAIME produces**: two texts in the repository contradict each other. The README asks for the express consent of a founder (MrJox, Maruka or Marthenil) before giving away files produced by CAIME, and forbids any commercial use, donations included. The EULA 1.1, which CAIME makes you accept at first launch, leaves you their owner and lets you publish them (Steam Workshop, Nexus Mods, ModDB) without monetising them; it discourages donations without forbidding them. **When in doubt, ask the team on its Discord before publishing.**
- The EULA also forbids any commercial automated pipeline producing content for third parties.
- The team asks you not to build another universe's map on a Warhammer game: use Troy or Pharaoh, same engine (CAIME team's Discord, 20.09.2026).
- Reusing another CA game's models in a Warhammer game is not allowed (Games Workshop restrictions): you need your own assets (CAIME team's Discord, 20.09.2026).
- **In short**: "CAIME: code under a non-commercial licence. Files it produces: the README asks for a founder's consent before giving them away, the EULA 1.1 lets you publish them without monetising them; when in doubt, ask the team before publishing; nothing commercial."

*Diagram: What CAIME allows, what to ask first.*

In the diagram: What CAIME allows, what to ask first · Allowed · modify CAIME's code · non-commercial licence: share-alike, copyright notice kept · make your own maps · the files it produces are yours (EULA 1.1) · publish the files it produces, without monetising them · Steam Workshop, Nexus Mods or ModDB (EULA 1.1) · Ask first, or don't · give away the files it produces · README: a founder's consent (MrJox, Maruka or Marthenil) · any commercial use · donations included, per the README · another universe's map on a Warhammer game · start from Troy or Pharaoh · another CA game's models · you need your own assets · The last two: the team's rules, stated on its Discord on 20.09.2026 · The README and the EULA 1.1 contradict each other. · When in doubt, ask the team on its Discord before publishing.

CAIME's code is under a non-commercial licence. For the files it produces, the README (a founder's consent before giving them away) and the EULA 1.1 (publishing allowed, without monetising) contradict each other: when in doubt, ask the team. The team stated the last two rules on its Discord on 20.09.2026.

Sources: the [CAIME repository](https://github.com/TW-Campaign-Map-Modding-Team/CampaignMapToolkit) (README, LICENSE, EULA) and, for the team's two rules, its Discord (Campaign Map Modding Team), read on 20 September 2026.

## Install and set up

1. Install the game's **Assembly Kit** from Steam (Library → Tools).
2. Download CAIME from the [releases page](https://github.com/TW-Campaign-Map-Modding-Team/CampaignMapToolkit/releases): the installer is `CampaignMapToolkit-win-Setup.exe`. **v1.0.1** of 23 September 2026 includes two fixes from our workshop: loading the database on any Windows whose decimal separator is the comma, and reading Warhammer I's mini-campaign maps. Updates can be automatic.
3. At first launch, accept the EULA; after an update, a *Changelog* window opens. If the view is black when a map opens (known bug), pan or zoom.
4. **Settings → Preferences** (Ctrl+P in CAIME): pick the game first (*Base game*), then *Browse* for that game's Assembly Kit. The right folder is `assembly_kit`: it holds `binaries`, `raw_data` and `working_data`. One path per game.
5. Still in the preferences: *Auto-save* writes `map_autosave.hex` next to `map.hex` every 5 minutes; *Auto-backup* stores `map_YYYY_MM_DD_HH_mm_backup.hex` in `backups\` every 10 minutes (*to keep* = 0 keeps all: several MB per copy on a large map; set 10 or 20). The Assembly Kit path and the database source apply the next time a project opens; auto-save starts or stops at once. Settings live in `%APPDATA%\CampaignMapToolkit\Caime\preferences.json`.
6. The database can come from the Assembly Kit (default) or from RPFM (*Database source*). In RPFM mode, CAIME needs `rpfm_cli.exe`, the one from an RPFM version 4 (for us, 4.2.7): version 5 no longer ships it. It also needs one *Vanilla pack* per game (for Warhammer III: `db.pack`); your mod's packs are added through *Settings → RPFM Workflow*.
7. Read the [documentation](https://tw-campaign-map-modding-team.github.io/CampaignMapToolkit/): twelve detailed guides, from getting started to exporting.

*Diagram: Setting up CAIME: the preferences window (diagram).*

In the diagram: Setting up CAIME · Settings → Preferences (Ctrl+P) · diagram · `Preferences` · Base game · `Warhammer 3` · Assembly kit path · `<game>\assembly_kit` · `Browse` · Auto-save · `Enabled` · `Disabled` · Auto-backup · `Enabled` · `Disabled` · Auto-backups to keep · `10` · Database source · `Assembly Kit` · The game before Browse: one path per game. · `assembly_kit\` · Browse: this folder · `binaries\` · `raw_data\` · `working_data\` · Auto-save → · `map_autosave.hex` · every 5 min · Auto-backup → · `backups\` · every 10 min · Auto-backups to keep: 0 keeps all; set 10 or 20 · Assembly Kit: the default · RPFM: rpfm_cli.exe from a version 4 and a Vanilla pack: db.pack · version 5 no longer ships it

In Settings → Preferences (Ctrl+P): the game first, then its Assembly Kit path, the automatic saves and the database source. The path and the source apply the next time a project opens, auto-save at once. A diagram, not a screenshot: only the settings this guide discusses.

Seen in v1.0.0 (20 September 2026), not checked in v1.0.1: the installer shipped neither the templates folder (`Templates`) nor the `MapDataBuilder` tool. Check: CAIME looks for that tool in `Tools\Release\MapDataBuilder.x64.exe`, under the parent of its executable's folder; with the official installer, that is `%LOCALAPPDATA%\CampaignMapToolkit\Tools\Release\MapDataBuilder.x64.exe`. If it is missing, ask the team first: building the repository takes Visual Studio, with C# and C++ (the solution holds both).

In Assembly Kit mode, CAIME **reads** the database (on open and on every *Reload*) and writes nothing. In RPFM mode it temporarily places tables there and restores the originals when the project closes: don't edit that kit's tables meanwhile, as the restore overwrites whatever is there.

## The window and the tools

With no project open, almost everything is greyed out. Once a map is open, the window has nine areas:

*Diagram: CAIME's window and its nine areas.*

1. **The menus**: File, Edit, Process, Tools, Settings, Help.
2. **Quick settings**: with Brush, the brush size (Brush size, 1 to 10); the background image opacity (Image opacity) and ✕ to remove it; with Flood Fill, the Flood Fill source list.
3. **The tools**: M Pan · Z Zoom · B Brush · F Flood Fill · E Eraser · I Background Image · L Line · P Color Picker; ⚙ Properties, greyed out in v1.0.1.
4. **The canvas**: the hex map; the brush circle. Wheel: zoom; middle click: pan.
5. **The minimap**: the red frame shows the view; a click there moves the view.
6. **The swatches**: the value to paint, in a drop-down list: the database keys for the active layer (here plains).
7. **The actions**: those of the active layer: Create, Rename, Remove (after the database), Cleanup…; Align, Plug Holes or Auto-generate depending on the layer; Validate.
8. **The layers**: the tick box makes a layer visible; the round button makes it active. Ground Types is at the bottom, active on opening.
9. **The status bar**: the last message (a click opens the Logger), X = column and Y = row under the mouse.

Diagram of the usual layout. To paint: pick the layer (8), then the value (6), then the tool (3), and paint on the canvas (4). The Logger (Ctrl+L) gives faulty hexes as Hex(column, row): move the mouse until the status bar (9) shows that X and Y.

### The recipe for painting

1. In **Layers**, tick the layer's box (it becomes visible) and click its round button (it becomes **active**: that is the one you paint).
2. In **Swatches**, pick the value: a ground type, a region, a climate…
3. In the toolbar, pick the tool (table below), set the brush size, and paint.
4. To check: the status bar gives X (column) and Y (row) under the mouse; Ctrl+Z undoes without limit, one mouse gesture at a time.

| Key | Tool | What it does |
|---|---|---|
| M | Pan | move the view (the middle click does it too, whatever the tool) |
| Z | Zoom | zoom (the wheel too) |
| B | Brush | paint; size 1 = 1 hex, 2 = 7, 3 = 19, 4 = 37 |
| F | Flood Fill | fill an area; the *Source* list says which layer acts as the border (Ground Types, Climates, Attritions, Regions, Impassable, Roads, Trade Routes, Restrictions) |
| E | Eraser | erase |
| I | Background Image | lay a background image (JPG, BMP, TIFF, PNG), stretched over the map: a working sheet, **never saved nor exported** |
| L | Line | a first click (in red), the path shows in yellow, a final click |
| P | Color Picker | pick a hex's value; holding Alt gives a temporary picker |

*Diagram: The brush: 1, 7, 19, 37 hexes.*

In the diagram: The brush: 1, 7, 19, 37 hexes · Size 1 · 1 hex · radius 0: the clicked hex · Size 2 · 7 hexes · radius 1 · Size 3 · 19 hexes · radius 2 · A Warhammer III town · Size 4 · 37 hexes · radius 3 · One click paints every hex at most size − 1 steps from the clicked hex. The Brush size slider goes from 1 to 10: 271 hexes at most.

The brush size is a radius: size 1 paints the clicked hex, each extra size adds a ring. Size 3 lays, in one click, the 19-hex disk of a Warhammer III town.

### Shortcuts worth knowing

| Shortcut | Action |
|---|---|
| Ctrl+N · Ctrl+O · Ctrl+S · Ctrl+Shift+S | new map · open · save · save as |
| Ctrl+X · Ctrl+Q | close the project (not "cut") · quit |
| **Ctrl+R** | **Reload**: reads the database again, and **discards anything unsaved** |
| Ctrl+Z · Ctrl+Y | undo · redo (no limit) |
| Ctrl+Shift+R · Ctrl+Shift+N | resize (margins right, left, top, bottom) · rename the map (the database and the folder under `raw_data` must follow) |
| Ctrl+L · Ctrl+B · Ctrl+M · Ctrl+P | Logger · Border Editor · Map Data Editor · Preferences |

The Logger gives faulty hexes as Hex(column, row): move the mouse until the status bar shows that X and Y, and you are on it.

## Building a new map, step by step

### Setting up the project

1. **Design.** Sketch, list of regions and provinces, towns, ports, chokepoints (see below). **Even** width: a requirement of the hex grid, says the documentation, which suggests 1016 × 720 and warns beyond 731,520 hexes (slowness, not a ban). The CAIME team mentions on its Discord (20.09.2026) a ceiling of 2,048 hexes per dimension, beyond which the AI's pathfinding data (hlp, spd) no longer generates; we did not find it in v1.0.1's code. Warhammer III's big map is 1440 × 970. Map name: letters, digits and underscores (CAIME silently strips the rest), and **case matters**.
2. **Declare the map in the database**, with that exact name (Dave, XML by script, or RPFM): see the next section and its column sheet.
3. **Create the project**: File → Create new map (Ctrl+N); exact name, *Template* = None, *Game* = Warhammer3 (**final**: the game is baked into the project), even width. CAIME stores the project in its `Projects\<map>\` folder; with the official installer, `%LOCALAPPDATA%\CampaignMapToolkit\Projects\<map>\`. Check: when it opens, the Regions layer's *Swatches* list shows your regions; if it is empty, the database does not know the map (see the FAQ).
4. **Put it in its place**: right away, File → Save as… (Ctrl+Shift+S) to `<Assembly Kit>\raw_data\EmpireDesignData\campaign_maps\<map>\map.hex`, then reopen that copy. Map Data and Dynamic Resources only work there (otherwise: "Map Data Process denied").

*Diagram: Two copies of your project.*

In the diagram: Two copies of your project · The draft · Ctrl+N creates it here · Map Data: denied here · `%LOCALAPPDATA%\CampaignMapToolkit\Projects\<map>\map.hex` · `File → Save as…` · `Ctrl+Shift+S` · reopen this copy · The real place · the only place Map Data works · `<Assembly Kit>\raw_data\EmpireDesignData\campaign_maps\<map>\` · `map.hex` · the project · Support files · `trees.png` · ≈ 7.04 × 7.37 px per hex · `tree_database.xml` · from the prologue · `dynamic_resources.png` · ≈ 2.54 × 2.40 px per hex · `dynamic_resources_database.xml` · from the prologue · Automatic saves · `map_autosave.hex` · every 5 min · `backups\` · every 10 min · `map_YYYY_MM_DD_HH_mm_backup.hex` · Before Process · Saved · Tweak and Terry closed · Project in raw_data · `Process` · What Process writes · one file per export · `<Assembly Kit>\working_data\campaign_maps\<map>\` · `map_data.esf` · `pathfinding.ppd` · `display\borders\borders.pbd` · `dynamic_resources.esf` · `<campaign>_lookup.bmp`

CAIME creates the project in its own Projects folder: that is a draft. Map Data and Dynamic Resources only accept the copy saved (Save as) into raw_data, with its support files: reopen it and work in that one; Process then writes into working_data.

### Filling, validating, exporting

1. **Add the four support files** next to the `map.hex`: `trees.png`, `tree_database.xml`, `dynamic_resources.png`, `dynamic_resources_database.xml`. Without them, Map Data or Dynamic Resources fail. In Warhammer III, copy the XML files from the prologue's folder (`wh3_main_prologue_map`) and size the images to your map: about 7.04 × 7.37 pixels per hex for `trees.png`, 2.54 × 2.40 for `dynamic_resources.png`. `trees.png` also feeds BOB's trees. Check: the four files sit next to the `map.hex`, under these exact names.
2. **Save (Ctrl+S), then File → Reload (Ctrl+R)** after every database change: CAIME reads again the regions, ground types, climates and attritions declared for this map. Reload discards anything unsaved.
3. **Paint the layers**: every hex needs a region, a ground type and a climate. Land and sea must agree (the ground type, the region's `is_sea`, and the hex).
4. **Validate**, layer by layer: Tools → Validate → <layer> (eleven entries, one at a time), or the Actions panel's *Validate* button for the active layer; on the command line, `validate --all` chains them. The checks change nothing. Check: the window that follows says "No issues have been found"; otherwise the Logger (Ctrl+L) lists the *Errors*, *Warnings* and *Info*. Fix the *Errors* (nuances in "Rules for a map that works"), read the *Warnings*, save.
5. **Export** (Process): Map Data, Dynamic Resources, Pathfinding, Borders, Lookup. Save first; Tweak and Terry closed. Map Data success: "Finished creating map". Check: in `<Assembly Kit>\working_data\campaign_maps\<map>\`, dated today, `map_data.esf` (CAIME treats a file of 10 KB or less as failed), `pathfinding.ppd`, `display\borders\borders.pbd` and `<campaign>_lookup.bmp`. Details: the "Exporting" section.
6. **Meanwhile, the visual half**: export the tile map (Tools → Export → Baseline Tilemap image, `tile_map.png`) for the Terry project, then [Terry](https://bretonia.dev/atelier/en/terry/) and [BOB](https://bretonia.dev/atelier/en/bob/).
7. **Build the pack, then generate the startpos** once both halves are ready. The three ways to the startpos: RPFM's *Build Startpos*, BOB's *Process start pos* action, or a hand-written `user.script.txt`. For us, only the hand-written way worked: [the tools guide](https://bretonia.dev/atelier/en/tools/). Then rebuild the pack with the startpos ([RPFM](https://bretonia.dev/atelier/en/rpfm/)) and test in game. Every change to the map means a new export, then a new startpos.

## Database tables to declare

The map's name (here `my_map`) is the same everywhere, case included; the campaign's name (here `my_campaign`) links `campaigns`, `campaign_map_playable_areas` and `campaign_map_roads`. Column names come from the Warhammer III kit's schemas (`raw_data\db\TWaD_<table>.xml`).

| Table | What it says | Columns that hold the map together |
|---|---|---|
| `campaign_maps` | the map, in the kit (in the game's packs, Warhammer III no longer has this table: the map is declared there through `campaigns.map_name` and `campaign_map_playable_areas`) | `mapname` = `my_map`; `minx`, `miny`, `maxx`, `maxy` |
| `campaigns` | the campaign whose `map_name` is the map; **otherwise the Lookup export refuses** ("no campaign uses the map") | `campaign_name` = `my_campaign`; `map_name` = `my_map` |
| `campaign_map_playable_areas` | the campaign playable area: camera limits and minimap files (update it before Map Data if the size changes) | `mapname` = `my_map`; `campaign_key` = `my_campaign`; `minx`, `maxx`, `miny`, `maxy`; `radar_file` (the minimap); `index`, an automatic number |
| `regions` | one row per region, land or sea, with a **unique RGB colour** (used by the lookup images) | `key`; `is_sea` (0 or 1); `r`, `g`, `b` |
| `campaign_map_regions` | links each region to the map | `campaign_map` = `my_map`; `region` = a `key` from `regions` |
| `region_to_province_junctions` | one row per region, to its province | `region`; `province`; `is_capital` |
| `provinces` | the province, if it is new | `key` |
| `campaign_map_roads` | road costs, per campaign | `key`; `campaign` = `my_campaign`; `threshold`; `movement_cost` |
| `campaign_map_areas_of_interest` | Warhammer III and Three Kingdoms: filtered by map name, otherwise an empty layer | `key`; `campaign_map` = `my_map` |

*Diagram: Declaring a map: the tables held by one name.*

In the diagram: Declaring a map · my_map : the same name everywhere, case included · `campaign_maps` · in the kit only · `mapname` · `my_map` · `minx · miny · maxx · maxy` · `campaigns` · `campaign_name` · `my_campaign` · `map_name` · `my_map` · without it: the Lookup export refuses · `campaign_map_roads` · `campaign` · `my_campaign` · `key · threshold · movement_cost` · `campaign_map_playable_areas` · `mapname` · `my_map` · `campaign_key` · `my_campaign` · `minx · maxx · miny · maxy` · `radar_file · index` · `<mapname>wh3_main_chaos_map_4</mapname>` · `<mapname>my_map</mapname>` · not the last · `<mapname>wh3_main_combi_map_5</mapname>` · never the last row: Map Data crashes · `campaign_map_regions` · `campaign_map` · `my_map` · `region` · `my_region` · different case: empty swatches · `regions` · `key` · `my_region` · `is_sea · r · g · b` · unique r g b colour: the lookup uses it · `region_to_province_junctions` · `region` · `my_region` · `province` · `my_province` · `is_capital` · `provinces` · if it is new · `key` · `my_province` · `campaign_map_areas_of_interest` · `key` · `campaign_map` · `my_map` · Global tables, already filled · `campaign_ground_types · climates · campaign_map_attritions` · Check: the regions show up in Swatches

Each card is a table from Warhammer III's kit; the dotted line runs from the parent card to the column that links them, and the same label carries the same value. The map's name comes back in five tables, spelt exactly the same, capitals included.

These tables have other columns, many of them marked as required in the kit: fill them in after a CA row, the prologue's (`wh3_main_prologue_map`) for instance. Global tables (`campaign_ground_types`, `climates`, `campaign_map_attritions`) are already filled. Region order matters: the exports read land first, then sea, in the order of `regions.xml`. Check: when the project opens (or after File → Reload, Ctrl+R), the Regions layer's *Swatches* list shows your regions.

Creating, renaming or deleting a region, ground type, climate, attrition or area of interest takes **two moves**: change the database, then, in the **Actions** panel, the matching button (Create, Rename, Remove), with the same name. *Remove* does not clear hexes already painted.

> **The last-row trap**: The Map Data export **crashes** when the processed map's row is the **last** one of `campaign_map_playable_areas.xml`: same content, only the order changes. The crash happens in a kit DLL that MapDataBuilder calls; as far as we know, v1.0.1 does not work around it. A tool that always appends at the end of the file drops every new map into it: make sure another row follows yours.

## The layers

A layer is one piece of information per hex. You paint them one by one, like sheets laid over the same grid; a needle stuck through one hex goes through every sheet and reads one value on each.

*Diagram: CAIME's layers stacked like transparent sheets over the same map, in panel order: ground types, climates, regions, rivers, towns, roads and impassable; a needle goes through the same hex on all of them.*

1. **Ground Types**: ground type: plain, forest, mountain, sea
2. **Climates**: the climate: required on every hex
3. **Regions**: each hex's region, and its borders
4. **Rivers**: rivers, with their directions
5. **Town Sprawl · Town Slots**: a town's slot (19 hexes in Warhammer III; a port: 16 + 3) and its sprawl
6. **Roads · Impassable**: roads, with their directions; what cannot be crossed

Each layer is a sheet laid over the same grid: for a given hex, one value per layer. The sheets follow the order of CAIME's panel, where the top layer is drawn over the others. Schematic: Warhammer III has fourteen layers, and a town covers 19 hexes.

Warhammer III's layers, with the names the editor shows, in panel order (the top one is drawn over the others):

| Layer | What you paint | Effect, tool or action |
|---|---|---|
| Impassable | forbidden hexes | *Plug Holes* action: fills one-hex holes |
| Roads | roads, with their directions | lower cost (`campaign_map_roads`); never a ring |
| Town Slots | the slots: *Main Settlement*, *Port*, *Slot 2*… | see "Towns" |
| Town Sprawl | each town's footprint | *Align Town Sprawl/Slot* action |
| Bridges | bridges, on sea hexes | see "Bridges" |
| Rivers | rivers, with their directions | on land only |
| Beaches | beaches | only on coastal land: landings |
| Restrictions | graded movement restrictions | can be lifted by a Lua script |
| Region Borders | drawn borders | *Auto-generate* action |
| Areas Of Interest | areas of interest | needs the `campaign_map_areas_of_interest` table |
| Regions | each hex's region | swatches to create (name + *Is sea?*) |
| Attritions | armies' wear | swatches to create |
| Climates | the climate: required on every hex | swatches to create |
| Ground Types | ground type: plain, forest, mountain, sea… | sets movement cost; *Align Ground/Region Type* action: derives land or sea from the regions |

A fifteenth layer, *Trade Routes*, does not appear in Warhammer III's panel: it only serves Rome II, Attila, Thrones of Britannia and Three Kingdoms. The other layers are two-state (present or not), except those with swatches.

## Rules for a map that works

The eleven validation checks give three levels; here they are as v1.0.1's code assigns them. **Error**: database/map mismatch (regions, ground types, climates, attritions), invalid index, misplaced bridge, slot on impassable, and the town-sprawl rules. **Warning**: hex without region, ground or climate, land/sea mismatch, split or empty region, rivers, roads, beaches, slot size… **Info**: remarks. Fix every mismatch, index and bridge Error before exporting; a sprawl Error on a town in a pass also exists on CA's map (five towns): judge it in game. CAIME **does not stop** you exporting with Errors (the documentation says: "Fix all errors before processing"): read the Logger (Ctrl+L). For reference, CA's Warhammer III map raises hundreds of warnings, and exports.

*Diagram: Validator severity levels: Error, Warning, Info (v1.0.1).*

In the diagram: Error, Warning, Info · from the code of CAIME v1.0.1 · Error · most serious · Fix before exporting · Database ≠ map: regions, ground types, climates, attritions · Invalid index · Bridge on land, impassable or without two shores · Towns · Slot on impassable (Impassable check) · Sprawl on impassable or outside its region · Sprawl in several blocks · Hazard 2 hexes away · Two hazard zones touching · Warning · worth reading · Hex without region, ground or climate · Land and sea disagree · Split or empty region · Passable region without a slot · Sea: more than 9 neighbouring land regions · River into the sea; misplaced road or beach · Main slot ≠ 19 or 16 hexes; port without sea · Sprawl without a slot · Info · a remark · Isolated hex: road, river, beach, region… · Sea: more than 5 neighbouring land regions · Three mutually adjacent road hexes (tight junction) · Region without a town, all impassable · Slot on impassable (Town Slots check) · CA's own map has 5 sprawl Errors: judge in game. · validate exits with 2 on a single Warning: read the report.

The eleven v1.0.1 checks sort each message into Error, Warning or Info, and CAIME exports anyway: fix the mismatch, index and bridge Errors, read the Warnings, and judge a town in a pass in game.

### Regions

- **Every hex** has a region, a ground type and a climate. An empty region endangers the startpos.
- A land region is **in one piece**: the validator warns that a split region may hinder the startpos generation. A land region without a town is painted entirely impassable.
- A sea region touches **at most 5 land regions** (advice, Info level); beyond 9, Warning: the AI slows down, especially with hordes.

### Towns: slot and sprawl

Every passable region has at least one town slot; otherwise, Warning. The main slot (*Main Settlement*) is a **perfect 19-hex disk** around the town's centre (one click of a size-3 brush); its centre becomes the town's position. A **port** town keeps the same disk, split: **16 land hexes** in *Main Settlement* and **3 consecutive rim hexes**, sea side, in *Port* (at CA: two on land, one at sea). The sprawl covers the 19 hexes. The validator counts (19 or 16); MapDataBuilder needs the disk: without it the town has no position and the campaign AI crashes. The *Align Town Sprawl/Slot* action lays the sprawl under each slot.

*Diagram: Inland town: 19 hexes.*

In the diagram: Inland town: 19 hexes · Impassable touching: fine · River 2 hexes away: Error · Impassable 3 hexes away: fine · Port town: 16 + 3 hexes · Port: 3 rim hexes, 1 of them at sea · Main: 16 land hexes · The sprawl covers the 19 hexes

CA's model: a perfect 19-hex disk (one click of a size-3 brush), whose centre becomes the town's position. Inland town: the whole disk as the main slot (brown line); a hazard (impassable, river, coast) either touches the sprawl or stays at least 3 hexes away, never 2. Port town: the same disk, split between 16 land hexes in the main slot and 3 consecutive rim hexes, sea side, in the Port slot (blue line); the sprawl (ochre) covers the 19 hexes.

- The sprawl is **one block** per region and never sits on impassable (Error). The documentation also forbids river and cliff, but v1.0.1's code does not check it, and a CA port town's sprawl necessarily covers coast hexes.
- A **hazard** (impassable, rivers and the whole coast) either **touches** the sprawl or stays **at least 3 hexes away**; never 2. Only one hazard zone in contact. Both rules are Errors.
- A port's sprawl may spill onto the sea.
- The documentation gives three different rules for Warhammer III; CAIME's code applies 19 and 16 to Warhammer I, II and III. When porting a Warhammer I map (7 hexes, 4 for a port), grow the slots from 7 to 19 hexes (16 + 3 for a port).

### Rivers and bridges

- A river is **on land only**: it runs towards the coast but stops on the last land hex; no edge points to the sea or off the map.
- A **bridge** spans water **painted as sea**, shore to shore: paint *Bridges* on those sea hexes and lead the road to the shore. CAIME itself marks the shore hexes touching the bridge (*bridge-cliff*). Warhammer III's database even has a sea ground type for waterways, `sea_river`.
- The validator (v1.0.1) raises three Errors: a *Bridges* hex on land, an impassable *Bridges* hex, a bridge not joining two separate shores. A *Rivers* line lies on land: it is **not bridged**.

*Diagram: A bridge, and what is not one.*

In the diagram: A bridge, seen from above · Road · Shore: worked out by CAIME · Sea, painted Bridges · Sea, painted Bridges · Shore: worked out by CAIME · Road · River crossed: a crossing penalty · Bridge on a Rivers line: Error

A bridge spans water painted as sea, from one shore to the other: paint Bridges on those sea hexes and lead the road to the shore; CAIME itself marks the shore hexes touching the bridge (bridge-cliff, hatched): nothing to paint. A Rivers line lies on land and is not bridged: a bridge on land is an Error. Warhammer III's database even has a sea ground type for waterways, sea_river.

### Networks: trees, never rings

Roads, rivers and trade routes form **trees**, with dead ends. A **ring** (a circuit with no end at all, such as a road looping around a province) makes **the export run forever**: that is the real danger, since nothing cuts it for you. Erasing a single hex is enough to cut it. The documentation also forbids the **triangle** of three mutually adjacent hexes; for roads and rivers, CAIME already drops one edge of every triangle when it computes their masks, but avoid it anyway.

*Diagram: A network as a tree, not a ring.*

In the diagram: A tree · a junction, dead ends · A ring · the export never ends · The ring, cut · one hex erased: two dead ends · A triangle · three mutually adjacent hexes

Roads, rivers and trade routes: a tree, with dead ends. The ring (a circuit with no end) is the real danger: the export runs forever, and CAIME never cuts it; erasing a single hex is enough. The documentation also forbids the triangle of three mutually adjacent hexes; for roads and rivers, CAIME already removes one of its edges when it recomputes the links. A tight junction (three mutually adjacent road hexes) forms that triangle: CAIME flags it as an Info.

## Designing a map that plays well

- Start from gameplay: passes, fords, straits, faction neighbourhoods, invasion routes. Corridors and strongholds, not a uniform plain.
- Biomes in zones: continuous ranges with two or three passes, forests in one block.
- Believable rivers: mountain sources, confluences, deltas.
- Roads as a tree: a province's towns linked, then the provinces together.
- Compact regions of similar size; ports where trade makes sense.
- Prototype small (200 × 150), validate, export the pathfinding, **then** go to the final size: resizing (Ctrl+Shift+R) adds empty canvas, it does not scale the drawing.

## Editing an existing map

Repainting with existing values does not touch the database. Creating, renaming or deleting a type, a region or an area of interest takes the database **and** the Actions panel button. Workflow: validate → save → re-export → rebuild the pack → **regenerate the startpos** → rebuild the pack.

*Diagram: After an edit, what to redo.*

In the diagram: After an edit, what to redo? · first validate and save; then re-export: Repaint · the database does not change · Always · Ground types, attritions, impassable, restrictions · `Map Data` · `Pathfinding` · Roads, rivers, beaches, bridges, slots and sprawls · `Map Data` · `Pathfinding` · Climates · `Map Data` · Region shapes (the Regions layer) · `Map Data` · `Borders` · `Pathfinding` · `Lookup` · Create, rename, delete · the database first, then the Actions button · A ground type · `Map Data` · `Pathfinding` · A climate, an attrition, an area of interest · `Map Data` · A region · `all exports` · Resize (Ctrl+Shift+R) · the playable area first, in the database · New hexes are empty · `all exports` · Then, always · Rebuild the pack · Regenerate the startpos · Rebuild it with the startpos · When in doubt, rerun everything: only Borders and Lookup, purely visual, can be redone alone.

Each edit means rerunning the exports of what it touches, and always Map Data (the gold column); creating, renaming or deleting goes through the database first. Then always come the pack, a new startpos and the rebuilt pack.

| Change | Database? | Exports to rerun |
|---|---|---|
| Repaint ground types, attritions, impassable, restrictions | no | Pathfinding, Map Data |
| Repaint roads, rivers, beaches, bridges, slots and sprawls | no | Pathfinding, Map Data |
| Repaint climates | no | Map Data |
| Region shapes (repaint Regions) | no | Borders, Pathfinding, Map Data, Lookup |
| Create, rename or delete a ground type | yes (`campaign_ground_types`) | Pathfinding, Map Data |
| Create, rename or delete a climate or an attrition | yes (`climates`, `campaign_map_attritions`) | Map Data |
| Create, rename or delete an area of interest | yes (`campaign_map_areas_of_interest`) | Map Data |
| Add, rename or delete a region | yes (`regions`, `campaign_map_regions`, `region_to_province_junctions`) | all |
| Resize (Ctrl+Shift+R, with its margins) | campaign playable area (`campaign_map_playable_areas`) | all; new hexes are empty |

That is what the documentation asks for: the exports of the changed layers, and always Map Data. When in doubt, rerun everything: on its Discord (20.09.2026), the CAIME team explains that changing a single hex means reprocessing almost everything; only `borders.pbd` and the lookup images, purely visual, can be redone alone. Why: the tw-modding wiki calls `pathfinding.ppd` and `spd_data.esf` critical as soon as the map data changes; and for us, Map Data exports run alone left a day-old `pathfinding.ppd` in place. Then regenerate the startpos.

## Exporting: what each export produces

- **Save first**: Map Data and Dynamic Resources refuse to run otherwise.
- **Map Data** goes through the MapDataBuilder tool: the project must sit in its `raw_data` place, and **Tweak and Terry be closed** (Terry is a mode of Tweak), for Dynamic Resources too. Don't rely on the warning: CAIME looks for a program named `Tweak.AssemblyKit`, while Warhammer III's kit ships `tweak.modder.x64.exe`. Success: "Finished creating map"; a `map_data.esf` of 10 KB or less is treated as failed.
- **Borders** opens a choice window (Land, Sea, TI, MI; according to the documentation, TI = *theatre island*, a detached island, and MI = *Mediterranean island*, a smaller island): keep the default boxes.
- **Dynamic Resources** crashed MapDataBuilder on Warhammer III in our workshop; it is unresolved. If it happens to you, report it to the team.
- **Trade Routes**: the layer does not exist in Warhammer III, but the game's campaigns ship a `trade_routes.ptd`, and `--all` produces it.
- **Our workshop's finding, on a single project**: the `map_data.esf` the Map Data export produces (MapDataBuilder, which relies on the kit's programs) is in ESF `0xABCB`, while CA ships theirs in `0xABCA`; for us, the startpos generation crashed until it was converted. Check with the CAIME team whether your version does it.

*Diagram: Process: each export and its files.*

In the diagram: Process: each export and its files · Saved first · Tweak and Terry closed · Project in raw_data · for Map Data and Dynamic resources · `Process` · `Map Data` · `Pathfinding data` · `Borders data` · `Dynamic resources` · `Trade Routes` · `Lookup and` · `Minimap images` · `<Assembly Kit>\working_data\campaign_maps\<map>\` · `map_data.esf` · success: the message · "Finished creating map" · 10 KB or less: failed · `pathfinding.ppd` · the docs wrongly say .bin · `borders.pbd` · in display\borders\ · its window: default boxes · `dynamic_resources.esf` · crashed for us on Warhammer III · `trade_routes.ptd` · the layer does not exist in Warhammer III · `<campaign>_lookup.bmp` · a single image, no minimap; the game reads .tga, .dds, .png

Each Process menu entry writes its file, and they all land in the same working_data folder. Map Data and Dynamic resources want a saved project, in its raw_data place, with Tweak and Terry closed (the padlocks).

| Export | File produced |
|---|---|
| Map Data | `map_data.esf` |
| Pathfinding | `pathfinding.ppd` (the "Processing & Exporting" page wrongly says `.bin`) |
| Borders | `display\borders\borders.pbd` |
| Dynamic Resources | `dynamic_resources.esf` |
| Trade Routes | `trade_routes.ptd` (games that have this layer; not Warhammer III) |
| Lookup | for Warhammer III, a single `<campaign>_lookup.bmp` image (read in v1.0.1's code; the documentation also mentions a minimap); BMP for Warhammer I to III, Troy and Three Kingdoms, TGA elsewhere |

Everything goes to `<Assembly Kit>\working_data\campaign_maps\<map>\`. The lookup image, `<campaign>_lookup.bmp`, comes out as BMP; the game reads the files named in the map's row of `campaign_map_playable_areas` (on the prologue: `overlay_file` and `minimap_lookup_file` as `.tga`, `campaign_overlay_lookup` as `.dds`, `radar_file` as `.png` for the minimap). The tw-modding wiki runs that BMP through BOB to get the `.dds` and `.tga` files; an out-of-date lookup does not crash the game, but the map overlays look a bit odd.

The **Tools → Export** menu also gives the borders as SVG, the tile map for Terry (*Baseline Tilemap image*, `tile_map.png`) and each layer as PNG or binary; **Tools → Import → Layer data** reads back a `.hex_layer` of the same size. The *Map Data Editor* only serves Rome II, Attila and Thrones: it refuses Warhammer III.

## From the command line

Started without arguments, CAIME opens the editor; with arguments, it works in the console. The [official documentation](https://tw-campaign-map-modding-team.github.io/CampaignMapToolkit/user-guide-command-line-interface/) describes two commands, plus `--help`:

```
CAIME.exe process  --map <map.hex> (--all | --map-data --dynamic-resources --pathfinding
                                   --borders --trade-routes --lookup)
CAIME.exe validate --map <map.hex> (--all | --rivers --town-slots --roads --bridges --beaches
                                   --regions --attritions --climates --ground-types
                                   --impassable --town-sprawl)
--map shortens to -m · exit codes: 0 success · 1 invalid arguments · 2 failure
```

*Diagram: A CAIME command, piece by piece.*

In the diagram: One command, piece by piece · `CAIME.exe process -m <map.hex>` · `--map-data --pathfinding` · `CAIME.exe` · The program; with no arguments, it opens the editor · `process` · The verb: process exports, validate checks · `-m <map.hex>` · The map: --map or its short form -m · `--map-data --pathfinding` · The tasks: one flag per export, or --all alone · Exit codes · 0 success · 1 invalid arguments · 2 failure · validate exits with 2 on a single Warning, even on CA's maps: read the report. · --all includes Dynamic Resources (a crash for us on Warhammer III): list the tasks · `--map-data --pathfinding --trade-routes` · `--lookup` · and Borders from the Process menu

A command line reads in pieces: the program, the verb, the map, then the tasks. The exit code tells whether it all worked; read the report anyway.

- `--all` chains Map Data → Dynamic Resources → Pathfinding → Borders → Trade Routes → Lookup; it cannot be combined with individual flags.
- The Assembly Kit path is set in the editor first (Ctrl+P). `validate` does not need it, but without it, the checks comparing the map with the database see nothing.
- `validate` exits with 2 as soon as one check fails, a single Warning is enough, and even CA's maps fail: **read the report** rather than stopping a script on that code.
- The official command line only does `process` (the exports) and `validate`; a `.hex_layer` layer is written by script but imported through the window (Tools → Import → Layer data).
- **Caveat on `--all`** (v1.0.1, not retried): it includes Dynamic Resources, which crashed MapDataBuilder on Warhammer III for us, and Borders, whose options are only set by its window: in v1.0.0, `process --borders` without the window failed for us, and v1.0.1's code has not changed on that point. `--all` may therefore exit with 2: list the tasks instead (`--map-data --pathfinding --trade-routes --lookup`) and run Borders from the Process menu.

> **Our fork, to script everything**: To port a whole map without opening the window, our workshop added more commands to CAIME: create a map, import and export layers, read names, sync names with the database. They are not published for now; the two core fixes, however, are in the official version.

## Producing layers by script

For a large map, painting by hand is not enough. A `.hex_layer` is a simple file: **4 bytes** (a little-endian integer: the layer id), then **one byte per hex**, row by row, **from row 0, at the bottom of the map** (two bytes per hex for regions). The file is exactly 4 + W × H bytes (4 + 2 × W × H for regions), otherwise the import is refused.

*Diagram: CAIME's grid: row 0 is at the bottom, odd columns are shifted up; hexes are read row by row from the bottom left, and a .hex_layer file starts with a 4-byte id followed by one byte per hex.*

In the diagram: Row 0 · Row 1 · Row 2 · Row 3 · Column · index = row × width + column · The .hex_layer file · one byte per hex (two for regions) · id (4 bytes) · … · Edge mask · Bit 0 = north

CAIME's grid: row 0 at the bottom, odd columns shifted up, hexes read row by row from the bottom left; a .hex_layer file starts with a 4-byte id, then one byte per hex. The six bits of an edge mask (roads, rivers, borders) follow the sides, 0 at the north.

| Id | Layer | Value on disk |
|---|---|---|
| 0 | Impassable | **1 = passable**, 0 = impassable (in the file; in the editor, painting Impassable makes the hex impassable) |
| 1, 2, 6 | Trade Routes, Roads, Rivers | the edge mask (six bits) |
| 3 | Town Slots | index + 1: 0 = none, 1 = main (*Main Settlement*), 2 = *Port*, 3 = *Slot 2*… up to 12 (indices 0 to 11) |
| 4, 5, 7 | Town Sprawl, Bridges, Beaches | 1 = yes; any other value means "no" |
| 8 | Region Borders | the edge mask (six bits) |
| 9 | Regions | two bytes: v × 8 in little-endian, with v = index + 1 (first byte = (v × 8) mod 256, second = v ÷ 32) |
| 10, 11, 12 | Attritions, Climates, Ground Types | index + 1 |
| 13, 14 | Restrictions, Areas Of Interest | no format: neither import nor export of a `.hex_layer` |

- **Edge mask**: bit 0 = north, 1 = north-east, 2 = south-east, 3 = south, 4 = south-west, 5 = north-west. On import, only presence counts for roads and rivers (value > 0): CAIME recomputes their masks, linking every painted neighbour except the edge that would close a triangle. Trade-route masks are kept as they are; Region Borders is recomputed from Regions on save, when the regions have changed.
- Indices follow the project's order: **land first, then sea** (a sea type with index j is worth "number of land types + j").
- **Indices change from one game to another** (13 land ground types and 24 climates in Warhammer I, 15 and 40 in Warhammer III): match them **by name**, never by number.
- Only reimport the layers you actually changed: reimporting Roads or Rivers recomputes all their masks, and the original map's links are lost, even though the hex count stays the same.
- CAIME's PNG export flips the image to look like the game: an image drawn "top up" must be flipped before encoding.

Our method: a painted image (one colour = one value) and a legend → one `.hex_layer` per layer → import into CAIME (in the official version, through the window: Tools → Import → Layer data) → PNG export to check → validation → fix the image, and repeat. The image and the legend stay the source of truth; the `map.hex` is the product.

*Diagram: From an image to a .hex_layer file.*

In the diagram: From image to .hex_layer · An image, north up · one pixel per hex, one colour per value · N · Start from the bottom: row 0 · the file begins with the image's bottom row · `row 0` · One colour, one value · the layer's legend; here, Roads · `road → 1` · `none → 0` · Write the bytes · Header · One byte per hex · `02` · `00` · `00` · `00` · `01` · `01` · `00` · `00` · `00` · `00` · `…` · `2 = Roads` · row 0 first · exact size: 4 + W × H bytes, or it is refused · Regions: 2 bytes per hex, so 4 + 2 × W × H · Tools → Import → Layer data · Roads: only presence counts; · CAIME redoes the directions · Check, then validate · Tools → Export → Layer data: the PNG comes out north up; compare it with the drawing, then run Validate · = · drawing · PNG · Encodings that bite · `Impassable (0)` · 1 = passable, 0 = impassable · `Regions (9)` · two bytes: v × 8, with v = index + 1 · `v = 5 →` · `28` · `00` · `v = 40 →` · `40` · `01` · `Town Slots (3)` · 0 = none · 1 = main · 2 = Port · `Restrictions (13), Areas Of Interest (14)` · no .hex_layer file

A layer by script: the painted image, read from the bottom row, translated through its legend, written byte by byte after a 4-byte header; then the import, the PNG export to compare it with the drawing, and the validation.

## Porting a map from another Total War game

That is what we did with The Season of Revelation's map (Warhammer I → Warhammer III, 400 × 440 hexes, 61 regions). The steps specific to a port:

- Read the original map's layers (CAIME opens Warhammer I's mini-campaign maps since v1.0.1) and **match them by name** to the target game's lists.
- **Match faction keys on culture and the end of the key**, never on the prefix: `wh_dlc05_brt_mini_bastonne` in Warhammer I is `wh_main_brt_bastonne` in Warhammer III.
- Grow the settlement slots from 7 to 19 hexes (16 + 3 for a port), as a disk around their centre, and redo the sprawls.
- Keep the file names of the original `campaign_map_playable_areas` row (the `radar_file` column, for example: the minimap): a column that names a file is checked against the pack's actual contents.
- Keep the other game's files **out of anything you publish**: they belong to CA.

*Diagram: From Warhammer I to Warhammer III.*

In the diagram: From Warhammer I to Warhammer III · CAIME 1.0.1 opens Warhammer I's mini-campaign maps · Warhammer I · Warhammer III · Towns · 7 hexes · port: 4 · 19 hexes · port: 16 + 3 · Grow each slot into a disk around its centre, then redo the sprawls · Ground types and climates · 13 land ground types · 24 climates · 15 land ground types · 40 climates · Re-match the indices by name, never by number · Faction keys · `wh_dlc05_brt_mini_bastonne` · `wh_main_brt_bastonne` · Same culture (brt), same end of key (bastonne): never the prefix · The minimap · `radar_file` · from the original row · The same name, checked in the pack · A column that names a file is checked against the pack's contents · Warhammer I files: never published, they belong to CA.

Porting a map is mostly re-matching: towns as 19-hex disks, ground types and climates by name, faction keys on the culture and the end of the key; the file names of the original row are kept. And nothing from Warhammer I gets published.

The full story: [the porting tutorial](https://bretonia.dev/blog/en/tutorial-porting-a-warhammer-1-map-to-warhammer-3.html) and [the nine walls of the port](https://bretonia.dev/blog/en/the-9-walls-of-porting-a-map-to-warhammer-3.html).

## The pitfalls that cost us the most

*Diagram: Where the traps bite.*

In the diagram: Where the traps bite · The database · A different case in the name: empty swatches · The map as the last row of campaign_map_playable_areas: Map Data crashes · No campaign cites the map: Lookup refuses · Renaming the map (Ctrl+Shift+N): the database and the folder must follow · The project in CAIME · The project's game is final · Reload (Ctrl+R) throws away anything unsaved · Ctrl+X closes the project · The background image is never saved · Resizing does not scale the drawing · The layers, painted or scripted · A ring with no end: the export runs forever · A .hex_layer starts from row 0, at the bottom · Impassable = 1 means passable · Indices are matched by name, never by number · Process · Tweak or Terry open: close both · Support files missing: Map Data fails · Dynamic Resources: a crash for us · The Map Data Editor refuses Warhammer III · The startpos · Every export needs a new startpos · The exported map_data.esf in ESF 0xABCB: generation crashed, on one project · The documentation contradicts itself in places: trust the validator and the disk.

The guide's main traps, at the step where they bite: the database, the project, the layers, Process, the startpos. The details, and the reasons, in the list below.

- **Reload (Ctrl+R) throws away anything unsaved**: Ctrl+S first, always.
- **The project's game is final**: a project created for the wrong game is redone (see the FAQ).
- **Missing support files**: Map Data or Dynamic Resources fail. Copy them from the prologue.
- **A ring with no end** of roads or rivers: the export runs forever (the documentation also names the triangle).
- **Impassable = 1 means passable**, in a `.hex_layer`: the opposite of intuition.
- **Row 0 at the bottom**: a map drawn "top up" ends up upside down.
- **Tweak or Terry open** during Map Data or Dynamic Resources: close both. CAIME's warning ("Please close Tweak.AssemblyKit") looks for a program that is not Warhammer III's kit one (`tweak.modder.x64.exe`): don't rely on it.
- **Ctrl+X closes the project**: it is not "cut". If unsaved changes remain, a question catches you: answer No.
- **Ctrl+Shift+N renames the map**, but the database (`campaign_map_regions`, `campaigns`, `campaign_map_areas_of_interest`) and the folder under `raw_data` must follow the new name.
- **No campaign cites the map**: the Lookup export refuses.
- **The map's row in last position** of `campaign_map_playable_areas`: Map Data crashes.
- **Layer indices shift** when the database or the game changes: match them by name.
- **A game update wipes your kit rows**: Steam updates the Assembly Kit after the game (for us, an hour later, with 9.0) and rewrites `raw_data\db`, which CAIME reads; the rows added for your map disappear. Before reopening the project or exporting, look for your campaign's key in `campaigns.xml`, and restore your rows from your copies.
- **Resizing does not scale**: it adds empty hexes to paint.
- **The background image is never saved**: reload it every session.
- **The black view** when opening: pan or zoom.
- **The Map Data Editor refuses Warhammer III**: it only serves older games.
- **The repository's Warhammer III templates** (`wh3_main_combi_map_1`, `wh3_main_chaos_map_2`) are old versions without support files; the Assembly Kit's current maps are `_map_5` and `_map_4`.
- **The documentation contradicts itself** on a few points: `.bin` or `.ppd` for the pathfinding (the code writes `pathfinding.ppd`), the *bridge-cliff* ("ground type" in the documentation, computed in the code), the sprawl rules (river and cliff forbidden in the documentation, only impassable in the code), slot sizes in Warhammer III, the colours of the severity levels, "more than 9 neighbours" as Warning or Error, the ⚙ button, what *Baseline Tilemap image* contains (the code draws sea, roads, rivers, beaches and cliffs), the Map Data Editor configuration as `.json` or `.xml`, the sample Assembly Kit path, and whether you can paint on a hidden layer. Trust the validator and the disk.

## For an AI reading this page

If you are an AI helping someone build a map with CAIME, here are the essentials as checkable rules. These facts were gathered on CAIME 1.0.1 and game patch 8.1 (September 2026), then reviewed for update 9.0: check them again after an update.

- Ask the human before launching the game, driving the screen or publishing; delete nothing: tidy away, only the human deletes.
- No reverse engineering and no workaround of a CA tool: when a tool gets stuck, a control case, then the community (CAIME's Discord, tw-modding).
- Chain order: database → CAIME (paint, validate, export) → Terry and BOB → pack → startpos (generated by the game, pack loaded) → rebuilt pack → in-game test.
- Project: `<Assembly Kit>\raw_data\EmpireDesignData\campaign_maps\<map>\map.hex`, saved, with `trees.png`, `tree_database.xml`, `dynamic_resources.png`, `dynamic_resources_database.xml` next to it; Tweak and Terry closed (CAIME's warning looks for `Tweak.AssemblyKit`, Warhammer III's kit runs `tweak.modder.x64.exe`); output in `working_data\campaign_maps\<map>\`: `map_data.esf`, `pathfinding.ppd`, `display\borders\borders.pbd`, `<campaign>_lookup.bmp`.
- Backups: `map_autosave.hex` next to `map.hex` (5 min), `backups\map_YYYY_MM_DD_HH_mm_backup.hex` (10 min).
- Database: in Assembly Kit mode, CAIME reads `raw_data\db` without writing to it; in RPFM mode, it places tables there for as long as a project is open and restores the originals on close.
- After a game update, Steam updates the Assembly Kit and rewrites `raw_data\db`, added rows lost: check the campaign's key in `campaigns.xml` before reopening or exporting, and restore from the copies.
- Official command line: `CAIME.exe process|validate --map <map.hex> (--all | flags)`; codes 0, 1, 2; `validate`'s code 2 is not enough to conclude (a single Warning triggers it): read the report. `--all` includes Dynamic Resources (MapDataBuilder crash on Warhammer III for us); `process --borders` without the window failed in v1.0.0 and the code has not changed in v1.0.1: list the tasks. A `.hex_layer` is imported through the window (Tools → Import → Layer data).
- `.hex_layer`: 4-byte id (little-endian, 0 to 12), then one byte per hex from row 0 at the bottom (regions: two bytes, v × 8 little-endian, v = index + 1); exact size 4 + W × H (4 + 2 × W × H for regions); edge masks: bits 0 to 5 = N, NE, SE, S, SW, NW; Impassable: 1 = passable; Town Slots: 0 = none, 1 = main, 2 = Port, 3 = Slot 2… up to 12; Restrictions (13) and Areas Of Interest (14): no import or export format.
- Import: Roads and Rivers keep only presence (value > 0); CAIME links every painted neighbour except the edge that would close a triangle; Trade Routes masks are kept as they are; Region Borders is recomputed from Regions on save, when the regions have changed.
- *Baseline Tilemap image*: an image of 2 × W by 2 × H + 1 pixels (sea, roads, rivers, beaches, cliffs), the size of the Terry project's `tile_map.png`.
- Checks, as conditions: every hex has region, ground and climate; the region's `is_sea` = the ground's sea or land; land region in one piece; main slot = perfect 19-hex disk, its centre = the town's position; port town = 16 land hexes in the main slot + 3 consecutive rim hexes, sea side, in Port (one at sea); sprawl over the 19 hexes, never on impassable; hazard (impassable, river, coast) touching or at least 3 hexes away, only one zone in contact; river with no edge towards the sea or off the map; bridge on sea hexes between two separate shores (CAIME computes the *bridge-cliff*); no endless ring in Roads, Rivers, Trade Routes.
- Severities (v1.0.1): Error = database/map mismatch, invalid index, misplaced bridge, slot on impassable, sprawl rules; Warning = hex without region, ground or climate, land/sea mismatch, split or empty region, rivers, roads, beaches, slot size. Before exporting: zero mismatch, index and bridge Errors; a sprawl Error on a town in a pass also exists on CA's map (five towns): judge it in game. After every export: a new startpos.
- `map_data.esf`: for us the export came out in ESF `0xABCB` while CA ships theirs in `0xABCA`, and the startpos generation crashed until it was converted (one project; check with the CAIME team).
- Ground, climate and attrition indices are matched by name, never by number.
- Rights: "CAIME: code under a non-commercial licence. Files it produces: the README asks for a founder's consent before giving them away, the EULA 1.1 lets you publish them without monetising them; when in doubt, ask the team before publishing; nothing commercial."

## Sources and links

- [CAIME documentation](https://tw-campaign-map-modding-team.github.io/CampaignMapToolkit/) (twelve guides, including [the command line](https://tw-campaign-map-modding-team.github.io/CampaignMapToolkit/user-guide-command-line-interface/)), [the repository](https://github.com/TW-Campaign-Map-Modding-Team/CampaignMapToolkit) (and its source code, `main` branch, which settles it when the documentation contradicts itself) and [its releases](https://github.com/TW-Campaign-Map-Modding-Team/CampaignMapToolkit/releases).
- [Campaign Map Making for Warhammer III](https://tw-modding.com/wiki/Tutorial:Campaign_Map_Making_for_Warhammer_III) and [Startpos](https://tw-modding.com/wiki/Startpos) (tw-modding wiki).
- [RPFM manual](https://frodo45127.github.io/rpfm/manual/) and [RPFM For Dummies](https://tw-modding.com/wiki/Tutorial:RPFM_For_Dummies).
- [Terry introduction](https://wiki.totalwar.com/w/TWW_Assembly_Kit_Terry_Intro) and [Rules.bob](https://wiki.totalwar.com/w/Rules.bob_Documentation.html) (Creative Assembly wiki).
- Our other guides: [the tools](https://bretonia.dev/atelier/en/tools/), [RPFM](https://bretonia.dev/atelier/en/rpfm/), [Terry](https://bretonia.dev/atelier/en/terry/), [BOB](https://bretonia.dev/atelier/en/bob/) and [modding with an AI](https://bretonia.dev/atelier/en/ai/).

## Frequently asked questions

### My swatches are empty after creating the project: why?

CAIME cannot find the map in the database. Check the Assembly Kit path for the right game (Ctrl+P), and that the map name in `campaign_map_regions` matches yours exactly, capitals included. Then save and do File → Reload.

### Why does CAIME open everything read-only?

On any Windows whose decimal separator is the comma (French, German, Spanish, Italian…), versions before the culture fix fail to load the database and open everything read-only. The fix is in v1.0.1.

### The map opens all black: what should I do?

It is a known bug: pan or zoom the view.

### The Map Data export fails: what should I check?

That the project is saved in its place (`raw_data\EmpireDesignData\campaign_maps\<map>\map.hex`), that Tweak and Terry are closed, that the four support files are next to the `map.hex`, that the map's row is not the last one of `campaign_map_playable_areas`, and that the MapDataBuilder tool is installed (with the official installer: `%LOCALAPPDATA%\CampaignMapToolkit\Tools\Release\MapDataBuilder.x64.exe`).

### Why does the export run forever?

Most often a ring: a circuit of roads, rivers or trade routes with no end at all. Cut it by erasing one hex. The documentation also names the triangle of three neighbouring hexes; for roads and rivers, CAIME already drops one of its edges when computing their masks.

### Must I re-export everything after a change?

The documentation asks for the exports of the changed layers, and always Map Data. When in doubt, rerun everything: on its Discord (20.09.2026), the CAIME team explains that changing a single hex means reprocessing almost everything. Then regenerate the startpos.

### I picked the wrong game when creating the project: what now?

The game is baked into the `map.hex`. Create a new project of the same size, export each layer as binary (Tools → Export → Layer data), then import them into the new project (Tools → Import → Layer data).

### Where are my automatic backups?

`map_autosave.hex` (every 5 minutes) sits next to the `map.hex`; every 10 minutes the `backups` folder gets a copy named `map_YYYY_MM_DD_HH_mm_backup.hex`. Open them with File → Open, then Save as. During a session, Ctrl+Z goes back without limit.

### Why is my bridge refused?

A bridge is painted on sea hexes, shore to shore. The validator (v1.0.1) raises three Errors: a Bridges hex on land, an impassable Bridges hex, a bridge not joining two separate shores. CAIME works out the shore hexes itself. A Rivers line lies on land: it is not bridged.

### What shape should a town's slot take, and a port's?

A perfect 19-hex disk around the town's centre (one click of a size-3 brush): its centre becomes the town's position. A port town keeps the same disk, split: 16 land hexes in Main Settlement and 3 consecutive rim hexes, sea side, in Port (at CA, two on land and one at sea). The sprawl covers the 19 hexes. The validator only counts 19 or 16; without the disk, the town has no position and the campaign AI crashes.

### I paint and nothing shows: why?

Check the active layer (the round button), the visible layer (the tick box), the chosen swatch, and that the toolbar is not greyed out (no project open).

### Hundreds of warnings on a CA map: is that serious?

No: CA's Warhammer III map raises hundreds and exports all the same; it even has five sprawl Errors, on towns in passes. Fix every database/map mismatch, index and bridge Error, read the Warnings; the Info entries are remarks.

### What is the maximum map size?

Even width; the documentation warns beyond 731,520 hexes (slowness), and the CAIME team mentions on its Discord (20.09.2026) a ceiling of 2,048 hexes per dimension, which we did not find in the code. Warhammer III's big map is 1440 × 970.

### Can a Warhammer I map be ported to Warhammer III?

Yes: that is what we did with The Season of Revelation. Since v1.0.1, CAIME opens Warhammer I's mini-campaign maps; our journal tells the method step by step.

### Can I share the files CAIME produces?

CAIME: code under a non-commercial licence. Files it produces: the README asks for a founder's consent before giving them away, the EULA 1.1 lets you publish them without monetising them; when in doubt, ask the team before publishing; nothing commercial.
