The 9 walls of porting a campaign map to Warhammer III
Porting a Warhammer I map to Warhammer III mostly means running into walls. In four days I counted nine big ones. For each: what we saw, what was really going on, how to get past it, and what I took away from it.
A coast of our map on 24 September, stepped like a staircase and edged with a pale strip of water: water and coasts were one of these walls.
How to read these cards
Each wall follows the format of our error log: the symptom, the cause, the fix, then the lesson, in a box. The causes were found by Claude, Anthropic's AI assistant, often by reading a crash report. The symptoms were usually mine, spotted in game with a Warhammer I screenshot next to it.
↔ swipe the diagram
The nine walls, sorted by when they hit, from the terrain to the in-game picture. In red, those that crash the game; in brown, those that say nothing.
Technical terms are explained along the way. For the full method, in order, see the tutorial.
Wall 1: the impossible startpos
The startpos is the file that freezes a campaign's starting state: factions, characters, settlements, diplomacy. No startpos, no game. The game builds it itself, from the data you give it.
Symptom: on the morning of 21 September, startpos generation crashes on every attempt.
Cause: two defects in our data, one behind the other. Three of our ports didn't have CA's shape. And the declared minimap didn't exist: it had been fixed inside the pack, which every build wiped out.
Fix: export one of CA's maps and look at its port towns: a 19-hex disk, 16 on land and 3 on the sea side, as the port. Then fix the source, the kit's tables, and have the pack build check that every declared file exists. The first startpos came out on the 21st at 12:08 pm.
CA's model, read from its maps: a perfect 19-hex disk, whose centre becomes the town's position; 16 land hexes in the main slot, and 3 consecutive rim hexes, sea side, as the port (blue line). Three of our ports did not follow this model.
Wall 2: BOB doing nothing, silently
BOB is the Assembly Kit's builder: it turns the terrain project into files the game reads.
Symptom: BOB runs only 6 actions instead of a dozen. No relief, no textures, and no error. We lost an hour trying files at random.
Cause: a limit of the tool. For a map the game's database (the one in CA's packs) does not know, BOB runs only those 6 actions, without a message; adding the map to the kit's database or to a mod pack changes nothing.
The right way: a control case first, to clear our files: ChaosRobie's project, copied under another name, failed the same way. Then the community: the CAIME Discord, tw-modding. We know of no official way to lift this limit, and our guides rule out taking a CA tool apart or working around it.
↔ swipe the diagram
Six actions instead of a dozen, without a message: a control case tells whether it is your project or the kit's limit.
Wall 3: Athel Loren without settlement slots
Symptom: the terrain is ready, and my two tests late on the 21st crash as soon as the campaign loads.
Cause: the day before, the 36 rows giving slots to Athel Loren's 18 settlements had been dropped on a false check: “Warhammer III declares none for its elf regions”. Yet the game looks for every settlement's primary slot. Our first fix targeted something else, and the crash came back unchanged.
Fix: the rows restored from Immortal Empires' templates, plus a new check comparing our startpos with one from a campaign that loads. That check finds this defect on its own.
Wall 4: an AI without a map, and a pack that jumps the queue
Symptom: a crash when the game sets up the human player. Worse, two tests were running on an old startpos, and we thought the fix didn't work.
Cause: three causes, one behind the other. The startpos was generated without the AI's map data, the two files it uses to find its way (hlp_data.esf and spd_data.esf). One faction had an empty AI group. And the startpos inside the pack took priority over the copy sitting next to it.
Fix: generate with the option that produces the AI data, and ship it; give each faction the AI group CA gives it in Immortal Empires, otherwise its culture's.
↔ swipe the diagram
When it breaks tells you where to look: each symptom we went through, and the row or file that was missing.
With that wall down, the campaign finally loaded.
It works!!!! […] the map looks like nothing, but at least it loads.
Wall 5: the end-of-turn crash nobody saw
Symptom: my game on the evening of the 21st stops at the end of turn one. I didn't report it; Claude found it the next day, somewhat by chance, in the crash reports.
Cause: a campaign has two terrains. The second one, a battle terrain, is used from the first battle, even between two AIs. Ours had never been shipped.
Fix: build that battle terrain the way CA does, compile it with BOB, and have the pack build check that every declared file exists.
↔ swipe the diagram
A campaign map has two terrains: its own, and a battle terrain, named by the terrain_folder column of its campaign playable area.
Wall 6: “I don't recognise the map”
Symptom: 21 September, 10:50 pm, in game: “this is a bit of a mess”, then “I don't recognise the map” (translated).
Cause: Warhammer III models in place of Warhammer I's; 5,277 pieces of Chaos set dressing made visible to all by a wrong rule; the winter glade's snow wiped out, mistaken for a defect. Everything had been checked with numbers, nothing by eye.
Fix: Warhammer I's own files, which is why the Realm of The Wood Elves DLC is required to play; only natural set dressing visible to all; the snow redone the Warhammer III way.
Warhammer I
Warhammer III
The reference, and the result: Tal Eth Ayr and the Oak of Ages in Warhammer I (left), then our map in Warhammer III on 25 September, with the King's Glade and Orion's army. Every visual now goes through this comparison.
Wall 7: stuff flying everywhere
Symptom: 22 September, 10:40 pm, objects floating all over the place. Claude's audits only found 45.
Cause: a coordinate frame. In Warhammer III, objects live in hex space, while the terrain is stored in square pixels, over a depth shorter by a factor of √3/2. Our objects had been wrongly converted: squashed 13% towards the south, they floated or sank. The audits, run in the same wrong frame, saw nothing.
Fix: never convert object positions, and read the terrain at row z × √3/2. Checked in Terry at 11:23 pm: the waystones were back in the ground.
↔ swipe the diagram
Diagram. Objects live in hex space, the terrain in square pixels, over a depth shorter by a factor of √3/2. Never convert an object's position: read the terrain at the right place.
Wall 8: a sea without water
Symptom: 23 September, 3:40 am: “by the sea there's no water, just the sandy bottom” (translated). No sea, no rivers, no lakes.
Cause: to smooth the coastline, the same surface had been written into both of the terrain's height maps: height, the terrain, and sea_height, the seabed. No depth left: the game drew no water. Terry, on the other hand, showed it.
Fix: give each map its meaning back; the water was back at 4:06 am. The same day, a seabed raised near the coasts did it again. Hence the rule, now in the code: as on CA's maps, sea_height stays below 0 everywhere, even under land.
↔ swipe the diagram
Diagram, in cross-section. The game draws water at level 0, above the seabed (sea_height). Writing the same surface into both maps leaves no depth; on CA's maps the seabed stays below 0 everywhere, even under land.
Wall 9: the new game that thought it was a save
Symptom: no cinematic, no “How to play”, no victory mission, and a weird camera.
Cause: the startpos predated the campaign scripts. Its save counter (__save_counter) only goes to 1 if the scripts run during generation. Stuck at 0, it made every new game look like a save. The Claude session in charge of scripts tracked it down.
Fix: regenerate the startpos after any script change, plus an automatic check that the counter is 1.
↔ swipe the diagram
The startpos freezes turn 0 at the moment it is generated: everything it needs on turn one, scripts included, must exist before.
What the nine walls have in common
Read together, these walls boil down to four simple rules.
Compare with something that works (walls 1, 2, 3). A known-good control case settles things faster than ten hypotheses.
Read what the code was looking for (walls 3, 5). A crash report tells you which data was missing; a difference between two files is only a lead.
Judge by eye, in game (walls 6, 7, 8). The numbers looked fine while the map was unrecognisable.
Respect the order of things (walls 4, 9). The startpos is a snapshot, the pack wins over loose copies, and each change gets tested on its own.
Each of these mistakes is logged in our error journal, with the rule that prevents it. I explain how we keep it in Working with an AI on a big mod. And to see where all this is heading, the map of all Bretonnia is waiting for you.