
Photo by Jakub Żerdzicki on Unsplash
Citadel has been out for a week and a half. This is its first patch, and both of the bugs in it are older than the release — one of them considerably older.
Neither turned up in play. They turned up because I pointed the engine at something it had never been asked to draw: a volcanic world, for the next game. Nothing about that scene belongs in Citadel and none of it has come back with me. But the two faults it exposed were Citadel’s all along, sitting quietly in a shipped game, waiting for the right room.
That is the useful thing about building something new on old foundations. It walks into corners the old thing never had a reason to visit.
On the volcanic map, every creature standing in front of the lava melted into it. Not artfully. They went translucent and the background came through them.
The cause is in Citadel and has been since the effect was written. When a creature is standing in front of fire, the renderer washes it toward the background — that is deliberate, and it is why a body silhouetted against a blaze reads as overwhelmed by it rather than pasted on top. The test for “is there fire behind this creature” was: is the background saturated orange, and is it bright?
That is a good proxy for a blaze. It is also an exact description of an amber door lamp, a molten sea, and any fire-lit wall. The test had only the finished frame to go on, so it could not tell a fire from a warm-coloured light — and it never occurred to me to ask, because until now the only bright orange thing in Citadel was fire.
It now multiplies by how much fire is actually in the frame, taken from the same emitters that draw the flames. A blaze still overwhelms a body. A warning light does nothing at all.
The evidence for this one is my favourite part. Citadel’s shot suite renders seventy-four fixed frames and compares them, so any change to the renderer has to declare itself. Exactly one frame moved, by an eight-by-twenty-three pixel patch, and the visible difference was a small amber ring disappearing.
Which reads entirely backwards until you work out what the ring was. It was a door lamp’s glow, painted over a creature standing in front of it — the background showing through a body like a hole. It had been there since launch, in a corridor with no fire in it whatsoever, and I had walked past it for weeks reading it as part of the lamp. A bright artefact vanishing was the correct outcome.
The renderer will draw a limited number of fire emitters at once, and the budget is sixteen. Corpse pyres are capped to fit. Fireballs, it turns out, were added on top of that budget with no cap of their own — so once there were more than sixteen fireballs in the air the remaining budget went negative, and the code that trims the pyre list was handed a negative length.
That is not a graceful degradation. Swift traps on it and the process dies. The game quits.
Sixteen fireballs is a lot. It is also entirely reachable: drum ruptures chain into each other, a rocket splash makes one, and a fireball lives for three seconds. A room full of drums going up together is the exact case — and Citadel builds those rooms deliberately.
Nobody had hit it, as far as I know, because sixteen at once is a big moment even in a game that likes big moments. The only reason anyone ever built a scene with twenty-four fireballs in it was that I was pricing volumetric fire over open terrain and wanted a stress test.
It is fixed properly rather than patched: the budget is clamped so it cannot go negative, and the whole list is now capped the way the pyres always were — nearest kept, furthest dropped, which is what the budget was there to do in the first place.
No gameplay changes, no content changes, no balance changes. The forty-eight floors are the forty-eight floors. If you are partway down, your saves are fine.
Shipping now, via the built-in updater, the download page or Homebrew, whichever you prefer.