Now the Backlog Has Cards Too
Last post the game grew a face. This one is less glamorous and honestly more satisfying: two days of tiny fixes, the kind that individually sound like nothing and together make the thing stop annoying me. A frost tower that actually feels frosty, buttons that forgive a misclick, co-op aiming that aims, scroll wheels that scroll the right way. And, fittingly for a game built around picking cards, the whole project moved onto a board full of them.
The frost tower learned to chill a room
The frost tower used to be a sad little gun that did a bit of damage and slowed exactly one enemy. Now it behaves the way "frost" should. It borrows two ideas from the poison dart: it only fires at enemies that are not already chilled (no wasting shots re-slowing the same target), and on impact it spreads its chill across a cannon-sized area. Only the enemy it actually hit takes damage; everyone else in the radius just gets slowed, no collateral.
The neat part is the geometry. The shot still needs to home onto its target, so I couldn't reuse the cannon's splashRadius for the homing (a non-zero splash makes a projectile fly to a point instead of a target). So the area radius lives in a separate Projectile.frostRadius field, baked in at spawn from the per-level stats, and applied on hit. The projectile homes like a dart, then dumps a chill puddle when it lands. I also gave the impact a blue splash ring so you can see the freeze land instead of just wondering why the pack slowed down.
Clicks now fire when you let go
This one is small and I should have done it on day one. Every left-click action used to fire on press. Which means the instant your mouse went down on a level-up card, that card was picked, no takebacks. Press a button by accident and you were committed.
Now everything fires on release instead. Press a card, realize it's the wrong one, drag off it, let go: nothing happens. It covers the whole game in one swing: level-up cards, tower-pick cards, every menu and lobby button, the toolbar, the tower inspect panel, reroll and banish, click-to-restart, and placing or selecting towers on the board. Right-click drag-to-cancel stays on press because it already had its own escape hatch. It is the single most "why did I ever ship it the other way" change in the batch.
Two co-op papercuts and a scroll wheel that went backwards
The co-op refactor left a couple of splinters. First, aiming a tower in co-op did nothing. The client renders "shadow" entities whose local ids do not match the authoritative server ids, and the aim intents were being sent with the local id, so the server looked up the wrong entity (or none) and shrugged. The fix is a pure little networkifyIntent that swaps the tower id from local to network before the intent goes on the wire. Unmapped ids just pass through and the server no-ops them. TDD'd, naturally.
Second, making the level-up and tower-pick screens non-blocking for co-op had quietly broken single-player: since nobody freezes the shared server for one player's card pick, single-player was also running live, so enemies kept marching while you read your cards. Now single-player gates the simulation on an "is an overlay open" flag and freezes properly, while co-op returns early and stays live. Same code path, two correct behaviors.
And then the dumbest, most satisfying one: the mouse wheel scrolled the UNLOCK screen and the stage-select screen the wrong way. Flipped the sign. Done. Ten seconds of work, a lifetime of relief.
The project got a board full of cards
The other change this week is not in the game at all: td-survivors is now run off a Trello board. Claude Code talks to it through a Trello MCP server, so it can read a card, implement it end to end, push, comment back on the card with what it did, and slide it over to the test column. I wired the allow rules for those write tools into the project settings so it does not stop to ask permission every time it moves a card.
There is a joke in here that writes itself. This is a game whose entire progression loop is drawing three cards and picking one. Now the development process is also a stack of cards where I draw the next one and pick what to build. The backlog finally matches the genre. The nice thing in practice is that the fixes above stopped living in my head as a vague "the frost tower feels bad" and became discrete cards I could hand off one at a time, which is exactly why this batch is a pile of small done things instead of one big half-done thing.
Two days, no new mechanics, a much less irritating game, and a workflow that finally has a shape. Back to the cards, both kinds.