WARBIRDS.IO Dev Log

← All posts

Fire-control ranging, and the turret that swung off the beam

A playtester sent a screenshot of their destroyer with the main turret hanging out over the water off the port bow, and shells leaving the middle of the hull instead of the barrel. Two real bugs and a missing feature, all in the main battery — so here's a gunnery pass.

The turret that rode off the side

The trainable main turret aims in world space — its bearing comes straight off the snapshot so it can track a target independent of the hull's heading. To do that it hangs off the (un-rotated) model root, not the hull. That's fine for a tank, whose turret sits dead centre: a point at the centre doesn't move when you spin the thing around it. But a warship's forward turret sits up on the forecastle, tens of metres toward the bow — and that offset was being applied in world space. Point the ship north and the turret was forward; come left to a westerly heading and the turret stayed pinned to the old world bow line, swinging out over the beam as the hull turned under it.

The fix is to rotate the mount's bow offset by the hull heading every frame, so the turret rides the forecastle while its aim stays in world space. A quick numeric check pins it: at headings of 0°, 90° and 180° the turret lands exactly on the hull's forward point, not off the side.

Shells from the keel

The second bug was the same disease one layer down: the server spawned every main-battery round at the hull's centre point, six metres up, then sent it off along the gun's aim. From the bridge it looked like the shells were welling up out of the keel and slewing away sideways — the muzzle flash was on the barrel, but the round wasn't. Now the server computes a proper muzzle: the forward mount offset along the bow heading, up at deck height, plus the barrel length along the aim. The per-ship offsets mirror the client's models exactly, so a round leaves the barrel you're looking at. (The AI's guns share the same code, so their fire reads true too.)

Auto-ranging: aim where you point

The fight happens across kilometres of open sea, and a shell takes real seconds to get there and drops the whole way. Until now you compensated by eye — walking the reticle up above a distant hull and guessing the holdover. That's fun once and tedious forever, so the gunsight gets fire control. We built a first cut around a manual range-lock, then went to look at how World of Warships does it — and binned half our design.

WoWs doesn't make you set a range. The guns auto-elevate to wherever the crosshair points, continuously: you put the sight on the target and the fire-control solution is always live, so the only manual skill is leading a mover by eye. So that's what we do now. Each frame the client ranges the spot under the crosshair — it snaps to an enemy hull the line of sight passes over (a clean, steady range on a ship) and otherwise falls to where the sight meets the sea (so you can range open water and lead onto it). It feeds that range to the server, which lays the main battery to the flat ballistic R = (v²/g)·sin 2θ. The camera follows the sight while the barrels elevate underneath it; the centre of the sight is the point of fall. No lock, no holdover, no number to chase — a net deletion from our first attempt.

…but the shells still scatter

Auto-aim that always lands dead-on the crosshair would make gunnery trivial, and that's not how naval guns work — so, again following WoWs, a salvo disperses. Each round scatters within an ellipse around the aim, drawn from a Gaussian truncated at the ship's sigma, so most rounds cluster near the centre but the odd one flies wide, and the ellipse opens with range. A destroyer's quick rifles are tight; a battleship throws a looser pattern. Ranging and timing the salvo is the skill; the dice do the rest.

That one change quietly broke the fleet balance: with shells missing more, games stopped being decided by sinking and started being decided by the capture zones — and the map's western approach reaches the contested centre cap a touch sooner, so whichever side deployed west ran away with it (the headless probe caught an ugly 76–24 skew). The naval map is deliberately asymmetric — a natural coastline and scattered islands, not a mirror — so rather than flatten that character we share its tilt: the fleets swap which flank they deploy on each round, so the western edge belongs to each colour equally over a match.

Chasing that also turned up a deeper bug the lopsided map had been quietly cancelling: even after averaging the terrain, one colour still won — whichever team's hulls happened to step second in the tick. A ship stepped later aims at targets that have already moved that frame, a fresher firing solution. Alternating the step order each tick shares that second-mover edge evenly, and the fleets re-deploy fresh each round so a winning side can't snowball its survivors. Between them the probe settled back to a coin-flip — on the natural asymmetric map, with the shells still scattering.