← News  //  2026-07-10  //  v0.4.0

v0.4.0 - The flight toy learns to fight

The last three releases built the pieces of a space combat game: modular ships, objectives, and weapons that do damage. v0.4.0 is where those pieces finally point at each other and shoot. It lands on four fronts at once - weapons that find their target, a targeting layer that tells you what you are locked onto, an enemy with an actual brain, and a flight model that flies the hull honestly - and on top of all of it, the game makes noise for the first time. This is the biggest update so far; here is the whole of it, bolt by bolt.

Torpedoes that chase

In v0.3.0 the torpedo was a dumb projectile with a blast radius: aim, fire, hope. v0.4.0 turns it into a guided weapon, and it takes four separate pieces to do it well.

Proportional navigation

The torpedo steers toward its lock using proportional navigation - the same intercept law real missiles use, which turns toward where the target will be rather than where it is. Instead of chasing the target's current position (a tail chase that a moving target can outrun), the guidance nulls the rotation of the line of sight, so the torpedo settles onto a collision course and flies a lead that closes. A crossing target no longer buys itself safety just by not being where it was.

Launch aim-assist and the arming gate

An angular lock-on aim-assist gets the shot pointed in the right direction on launch, so proportional navigation starts from a sane heading instead of having to haul the torpedo around from a cold launch angle. An arming gate keeps the warhead inert for the first stretch of flight, so a torpedo that clips something on the way out - or that you fire with a target right on top of you - does not detonate in your own lap.

Reading the shot at a glance

Two visuals make the weapon legible. A launch particle burst marks the moment of fire, and a blast-radius visual shows the lethal volume when it goes off, so you can see whether a detonation actually reached its target or fell short.

The effect is that torpedoes stop being an area-denial gimmick and become a genuine threat you have to respect - both when you fire them and, later in this same release, when something fires them at you.

A targeting arc that knows what you are looking at

A guided weapon needs something to guide toward, so v0.4.0 adds a real targeting layer. It is not a single toggle but a graduated arc that starts wide and narrows down to a single component of an enemy hull.

Acquisition and focus dwell

Ships inside your 550 m acquisition range are auto-acquired by their signature - they show up as candidates without you doing anything. Dwelling your focus on one of those candidates promotes it: hold the reticle on a contact and it graduates from a loose acquisition to a full lock. The focus dwell is what separates "I can see it" from "I am committed to it", and a focus meter on the HUD fills as the dwell completes so you know when the lock is about to take.

Per-section fine-lock

From a full lock you can drill in. A per-section fine-lock lets you pick out an individual component of the enemy hull - a specific thruster, a turret, the torpedo bay - rather than the ship as a whole. Aim-snap pulls your aim onto the section so you do not have to be pixel-perfect, and cycling steps you between the available sections so you can walk your fire from a turret to a thruster to the hull. This is what makes the modular-ship foundation pay off offensively: you can dismantle a ship piece by piece instead of grinding down one health bar.

Turret auto-aim with true intercept lead

Turret fire plugs straight into this layer. Turrets auto-aim with true intercept lead, and the lead is solved in the shooter's own frame - so a moving ship's rounds actually land instead of trailing behind the shooter's own velocity. The turret prefers the fine-locked section if you have one, so your rounds converge on the same component you are picking apart; failing that it falls back to live structure on the locked target, and failing that to the camera ray, so it always has something coherent to shoot at.

The HUD substrate

Holding all of this up is a new HUD substrate: a general layer of screen-projected indicators that the targeting and turret systems draw on top of.

Anchors, apparent size, and edge arrows

Indicators anchor to entities or points and follow them through the world. They size themselves by apparent size, so a distant ship gets a small marker and a close one a large one, giving you a rough range read at a glance. When a target leaves the frame the indicator clamps to the screen edge with an arrow that points toward it, so you never lose track of where an off-screen contact sits relative to your nose.

Lead pips and the locked-target readout

On top of the anchors the substrate carries turret lead pips - markers that show you exactly where a turret is aiming its intercept solution, so the auto-aim is legible rather than a black box - and a locked-target readout that reports range, closing speed and health for whatever you have locked. Between the lock markers, the focus meter, the lead pips and the readout, the HUD finally tells you what the combat systems are thinking.

Friend, foe, or furniture

None of this means anything without a notion of sides, so v0.4.0 introduces a faction and relation model: every ship is hostile, neutral, or own. The relation is what the rest of the combat layer reads to decide what to do:

  • It drives acquisition - who gets auto-acquired and offered up as a target in the first place.
  • It stamps projectile allegiance - every round and torpedo carries the allegiance of whoever fired it, so your rounds do not collide with you, and a torpedo you shoot down dies whole and blast-free instead of cooking off in your face.
  • It sets reticle tint - the reticle is colored by the relation of whatever it is over, so hostile, neutral and own read at a glance without you parsing a label.

It is a small system that quietly makes the whole combat sandbox coherent.

An enemy with a state machine

The headline feature: v0.4.0 ships the first AI combat wave, and the enemy is no longer a stationary target. Each AI ship runs a behavior state machine and behaves differently in each state.

The five states

The machine has five states - Idle, Patrol, Engage, Evade, Retreat - and the ship picks its move from the state it is in. It flies autopilot-driven patrol routes when nothing is happening, transitions to engagement when a threat appears, breaks off to evade when it is under fire, and retreats when things have gone badly enough. Because the transitions are explicit, the enemy reads as having intent rather than twitching between behaviors.

Discipline, defense, and standoff

Inside those states the AI plays a real fight. It keeps fire discipline instead of hosing rounds indiscriminately. It prioritizes point defense on inbound torpedoes, turning its guns onto the biggest immediate threat rather than the nearest target. It holds a standoff orbit and strafes rather than flying straight at you, keeping range while it works. It remembers threats through a threat-memory model and evades the things that have hurt it. And once it has a firing solution, it launches its own enveloped torpedoes back at you - the same guided weapon you have, now pointed the other way.

Turning like a ship

The AI helm writes slewed absolute rotation commands rather than snapping to a heading, so the enemy turns like a ship with mass instead of instantly facing a new direction. Combined with the standoff orbiting, an AI ship moves the way a piloted one does.

This is the moment Nova Protocol stopped being a shooting range and started being a fight.

Flying the hull honestly

Underneath the combat is a flight-assist overhaul. The flight model got two distinct modes and a physical foundation that makes damaged ships fly like damaged ships.

Velocity-hold, Newtonian, and the RCS budget

There is now an assisted velocity-hold mode: WASDQE nudges push you around, an X brake latch holds you to a stop, and a soft speed cap keeps assisted flight civil. Alongside it sits a Z direct Newtonian mode for when you want raw thrust with no assist between you and the hull. Both modes spend from an RCS budget rather than commanding infinite authority, and a live FA and speed readout on the HUD tells you which mode you are in and how fast you are going.

Balancing thrust through the center of mass

The piece worth being proudest of: the flight computer balances thrust through the live center of mass. When a burn would induce torque - because your thrust line does not pass through the current center of mass - it uses differential throttle to null that torque, and it recruits off-axis thrusters for counter-torque when it needs more authority than the primaries alone can give. The payoff is that an asymmetric or battle-damaged ship still flies straight instead of pinwheeling: lose a thruster on one side and the computer compensates with what is left.

Mass-legible handling

Handling is now mass-legible. Turn rate is derived from the torque budget and the ship's live inertia, so a stripped ship snaps around and a heavy build lumbers, and the difference is something you feel rather than a number in a sheet. As part of this pass max_torque dropped from 100 to 40, tightening the relationship between mass and turn rate so heavier builds actually pay for their mass.

The chase camera

The chase camera got the same honesty treatment. It now smooths across all gameplay modes instead of only some, and it anchors on the live center of mass with a burn push-back lean so the frame settles back under acceleration the way a cockpit would.

All of this rides on the same foundation the game started from: a ship is not a monolithic model but a root entity with a handful of section children - hull, controller, thruster, turret, torpedo bay - each carrying its own mass and health and contributing exactly one behavior. Because the flight computer drives those real actuators rather than scripting a position, it stays honest about the hull it is given.

Sound and fury

And for the first time, the game has audio.

First SFX

Placeholder SFX cover the whole combat loop: explosions, impacts, turret fire, torpedo launches, and a throttle-tracking thruster loop whose pitch and volume follow how hard you are burning. Every cue plays with distance attenuation so far-off events are quieter, and with throttling so a busy fight does not collapse into a wall of noise.

Combat juice

Alongside the audio comes combat juice: a trauma-model camera shake that builds and decays with the action, and expanding hit and impact flash rings that mark where damage landed. Both are also distance-attenuated and throttled to match the audio, so the feedback stays proportional to how close and how busy the fight is.

One hit, one cue

The feedback stays crisp because one hit plays exactly one cue. The audio and juice observers ignore damage-propagation re-entry, so when a hit cascades damage through a ship's sections it does not fire a stack of overlapping cues. Underneath, the SFX and juice listener is an explicit marker on the gameplay camera, not "any Camera3d" - so editor previews and secondary cameras do not accidentally become listeners.

Fixes

A release this size shook out a long list of bugs and rough edges.

  • Skybox texture limit. The skybox cubemap is now reinterpreted into a 6-layer array at load time. The raw 24576 px image exceeded smaller GPUs' texture limit and killed the app on load; splitting it into an array keeps it under the limit.
  • Blast coverage. Blast damage now reaches every body overlapping the blast, not just one - so a detonation in a cluster hurts the whole cluster.
  • Physics interpolation. Ships, asteroids and torpedoes interpolate between physics ticks, so the camera stops twitching between updates, and the chase camera anchors on the live center of mass.
  • Projectile self-collision. Projectiles no longer collide with their shooter, shot-down torpedoes die whole and blast-free, and destroyed asteroids no longer leave rigid-body husks lying around.
  • Overkill and disabled controllers. Section overkill is absorbed instead of propagated, so a single massive hit does not cascade absurd damage onward, and a disabled controller stops torquing the hull instead of continuing to steer a dead ship.
  • Lead in the shooter's frame. Bullet lead is solved in the shooter's frame so a moving shooter's rounds land, and the AI helm writes slewed absolute rotation commands so it turns like a ship.
  • One cue per hit. Audio and juice observers ignore propagation re-entry, so one hit plays one cue.
  • Miscellaneous. The editor preview controller is made inert, the turret resting position is fixed, and a one-frame origin snap on camera-mode switch is gone.

Under the hood

A release this size came with plenty of plumbing.

Consuming bevy-common-systems

The integrity, health, blast and mesh-slicer systems now come from the shared bevy-common-systems crate instead of in-tree copies, so the same tested implementations back both the game and its siblings, and there is one place to fix a bug. As part of the same tidy the torpedo section split into its own module.

Example test ranges and the smoke harness

A row of example test ranges ships for exercising each system in isolation: 06_torpedo_range, 08_turret_range, 10_gameplay, and 11_com_range (the center-of-mass range). Each carries live tuning sliders and an FPS/version overlay, and there is a headless autopilot plus screenshot smoke harness that drives a scenario and asserts it initialized, so a broken scene fails loudly instead of silently.

Continuous integration

A new CI workflow runs on every PR and push to master: fmt, clippy, and the workspace test suite (with the windowed examples running under Xvfb). It is the first automated gate on the project, so regressions get caught before they land.

Point releases

Shortly after, v0.4.1 followed with a build and CI plumbing patch that leaves the game itself untouched. If you play Nova Protocol it is invisible; if you build or contribute to it, it is the difference between a green pipeline and a flaky one.

Fixing the macOS universal build

The release-flow now installs the x86_64-apple-darwin std for the pinned nightly. The macOS universal build stitches together the Intel and Apple-silicon slices, and it was failing because the pinned nightly toolchain was missing the x86_64-apple-darwin standard library target; installing it explicitly lets the universal build succeed.

One feature set across the CI matrix

CI consolidated onto a single --features debug feature set shared across clippy, tests and examples, so the whole run leans on one Bevy build instead of compiling several near-identical variants. On top of that the cache is now saved even when a job fails, so a red run still speeds up the next attempt, and the windowed examples smoke was pulled out into a separate, non-blocking step, so a flaky windowed run under Xvfb can no longer fail the whole pipeline.