Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ Three standing orders, all per unit and all honoured by the AI as well as the pl
| Order | Effect |
|---|---|
| `SET_EMCON` | silent turns off radar and active sonar together; free switches the radar back on |
| `SET_ROE` | HOLD refuses every engagement including automatic defence; TIGHT defends only; FREE fights |
| `SET_ROE` | HOLD refuses every engagement including automatic defence; TIGHT defends itself and fires only on HOSTILE contacts when ordered; FREE fights, and a commander's ship on FREE with automatic air defence engages identified hostile aircraft in its envelope (`AirDefence.engage_hostile_aircraft`) |
| `FORM_UP` / `BREAK_FORMATION` | station keeping on a leader, or steering for yourself again |

`AIController._manage_emissions()` makes emissions a decision rather than a default: a ship with
Expand Down Expand Up @@ -426,7 +426,10 @@ the target's speed, so a ship that has heard the weapon and is running is a much
works out which friendly ship each detected round is going for
(`threatened_unit`: the locked-on ship, else closest point of approach within 3 nm), sorts by
time to impact, and lets **any** ship in range engage. Escorts defend consorts, not just
themselves.
themselves. The force allocates as one, in two passes over the raid: every round first gets
one interceptor from the best-placed ship (`_rank_defenders`: a free guidance channel first,
then the nearest), and only then are budgets topped up and close-in guns given their turn.
One time-to-impact, the round's time to the ship it is going for, decides the budget.
4. `Unit.defensive_weapons()` returns interceptors longest-reach first, so layering is a property
of the data rather than hard-coded tiers. At most two interceptors are committed per round at
any moment; when they miss, the next layer gets its turn.
Expand All @@ -441,8 +444,15 @@ the target's speed, so a ship that has heard the weapon and is running is a much
### Engagement allowances
Defence is deliberately finite, so a large enough salvo gets through a good escort:
- `fire_control_channels` per platform caps how many rounds one ship can guide against at once.
- Two guided interceptors per round over its whole flight (shoot-shoot-look), and at most two in
the air at any moment.
- At most two guided interceptors in the air against a round at any moment, across the force
(`guided_budget`: one under `conserve` until the round is 45 s out, three under `saturation`).
- Each ship's layer has its own lifetime allowance against a round (`AirDefence.layer_key`, layer
and ship), so an escort's point-defence missiles never use up the defended ship's own.
- Networked fire control (`PlatformSpec.cooperative_engagement`): between two fitted ships on the
link, a radar-guided interceptor may be launched at a round below the shooter's own horizon when
the consort's emitting radar holds it inside its own (`WeaponManager.network_guide`), and the
shot fails if that support is lost. The same applies to aircraft on the plot
(`network_track_guide`). An unfitted consort's plot remains a cue only. Gameplay abstraction.
- Close-in weapons are exempt from channels and the guided allowance, since they are
self-contained, but get their own allowance of two bursts. One burst is modelled as a single
engagement, so a close-in magazine counts bursts rather than rounds.
Expand Down
28 changes: 27 additions & 1 deletion CURRENT_STATE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
# Current State: M36 + Command and recognition improvements
# Current State: M37 Integrated air defence, weapon fixes and flight operations

**Weapons.**
- A refused fire order now says why.
- A standing attack gives up on a plot that stays stale for four minutes.
- Rounds queued at a ship the plot records as sunk are refunded.
- Air-to-air and anti-air "direct" rounds fly at height instead of dying over land.
- A commander's ship on Weapons Free engages identified hostile aircraft in its envelope, one round at a time.
- The AI fires two SAMs at a fighter, not four.

**The air-defence network.**
- The force allocates as one: every inbound round gets an interceptor before any round gets a second, and a ship with a free guidance channel is asked first.
- Each ship keeps its own inner-layer allowance.
- Fitted ships on the link (`cooperative_engagement`: the 2027 US carriers, cruisers, destroyers and frigate, and Maya) can guide each other's shots below the shooter's own horizon.
- The Air Defence board names who has each round.

**Flight operations.**
- Jets hold instead of stopping in the air.
- An aircraft launched without orders holds ahead of its ship.
- Aircraft back at a busy or burning deck hold in a marshal stack astern.
- Helicopters are turned round in helicopter-deck time aboard a carrier.
- CAP intercepts are flown at dash.
- A deck can hold 2 or 4 fighters on ready alert and scrambles them toward a raid itself.

The [M37 note](docs/2026-10-03-integrated-air-defence-and-flight-ops.md) gives the audit findings, the design, before-and-after battle measurements and what was deliberately left alone.

# Previous: M36 + Command and recognition improvements

22 aircraft and all 14 submarine entries now use improved original recognition models, with matching portraits, thumbnails, profiles and tactical-map plans. Aircraft have tapered wings, framed canopies, intake openings and clearer family silhouettes. Submarines have rounded bows, faired sails, corrected bow/sail planes, class-specific stern controls and open pump-jet shrouds or screws. The [combined art and command review](docs/2026-10-02-aircraft-submarines-and-integration.md) records scope and integration checks.

Expand Down
9 changes: 9 additions & 0 deletions HANDOFF.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Handoff

Latest: M37, [integrated air defence, weapon fixes and flight operations](docs/2026-10-03-integrated-air-defence-and-flight-ops.md).
- **Defence cycle.** `AirDefence.run_cycle` is now two passes over the raid, ranked by `_rank_defenders`. The per-layer lifetime allowance is keyed by `AirDefence.layer_key` (layer and ship).
- **Networked guidance.** It lives in `WeaponManager.guidance_available`, `network_guide` and `network_track_guide`, gated by `PlatformSpec.cooperative_engagement` on both ships. Interceptors no longer take the shooter-radar check at the top of `_step`; `_step_interceptor` checks guidance itself.
- **Weapons Free against aircraft.** `AirDefence.engage_hostile_aircraft` runs only for a player side with no AI controller.
- **Holds.** `Movement.enter_hold` lays a racetrack and marks it (`Unit.hold_active`/`hold_point`). Anything deciding whether a unit is idle must use `Unit.has_route()`, not `waypoints.is_empty()`; the AI search did the latter and stalled until it was changed.
- **Marshal.** `AviationManager.deck_can_recover`, `in_marshal` and `marshal_point`.
- **Ready alert.** `Unit.ready_alert`, `Order.set_ready_alert` (a new `SET_READY_ALERT` order type, appended to the enum) and `AirMissionManager._scramble_alerts`.
- **Generators.** They need `shapely`. Even with it, the generator sequence did not reproduce `data/` byte for byte in the cloud container, so data was edited by hand to match the generator output, and the generator carries the same change.

Latest art pass: 22 aircraft and all 14 submarine catalogue entries have revised original geometry, matching portraits/map plans and a shared `submarine_coating` world finish. `tools/art/build_air_subs.py` overrides the old builders; regenerate with `tools/art/rebuild_air_subs.sh` (copies donor derivatives last). Do not regenerate these entries with the legacy Blender source. `tools/recognition_playtest.gd` checks every revised entry through the real Reference viewer, including all three camera presets. See [the combined art and command review](docs/2026-10-02-aircraft-submarines-and-integration.md).

Latest deeper pass: [Classic, uncertainty and guided command](docs/2026-10-02-deep-command-review.md). `CommandGuide` observes accepted player orders and held reports; progress is saved in Main's presentation dictionary, not simulation fields. Briefing F1 can resume it. New native coverage: `tools/deep_command_playtest.gd`. Classic is now [1, 2, 4, 8], manual SAMs, auto-attack off. Explicit saved values always win; legacy 4×/auto-attack remains Custom. `WorldPresentation.plotted_entry` must never read a hidden specification: class representatives come from `MapSymbols.platform_for_class`, altitude from the Track. Visual sightings now also check terrain. Known sensor-only models are tinted, and captions distinguish SIGHTED, SENSOR ESTIMATE and BEARING ONLY/NO CURRENT FIX.
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_cg_ticonderoga.tres
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sensor_ids = PackedStringArray("an_spy_1b", "an_sqs_53c", "an_slq_32")
mast_height_m = 32.0
aircraft_capacity = 2
fire_control_channels = 8
cooperative_engagement = true
decoy_count = 18
torpedo_decoy = "AN/SLQ-25 Nixie"
towed_torpedo_decoy = true
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_cvn_ford.tres
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sensor_ids = PackedStringArray("ford_dbr", "an_slq_32")
mast_height_m = 50.0
aircraft_capacity = 75
fire_control_channels = 2
cooperative_engagement = true
decoy_count = 24
torpedo_decoy = "AN/SLQ-25 Nixie"
towed_torpedo_decoy = true
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_cvn_nimitz.tres
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sensor_ids = PackedStringArray("an_sps_48", "an_slq_32")
mast_height_m = 50.0
aircraft_capacity = 68
fire_control_channels = 2
cooperative_engagement = true
decoy_count = 24
torpedo_decoy = "AN/SLQ-25 Nixie"
towed_torpedo_decoy = true
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_ddg_arleigh_burke_iia.tres
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ health = 110.0
weapon_loadout = {"rgm_139_vla": 8, "mk45_mod4_gun": 250, "sm2_family": 24, "essm_family": 32, "phalanx_ciws": 60, "tomahawk_block_v": 8}
aircraft_capacity = 2
fire_control_channels = 6
cooperative_engagement = true
decoy_count = 12
decoy_effectiveness = 0.35
torpedo_decoy = "AN/SLQ-25 Nixie"
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_ddg_burke_iii.tres
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ sensor_ids = PackedStringArray("an_spy_6", "an_sqs_53c", "an_slq_32")
mast_height_m = 30.0
aircraft_capacity = 2
fire_control_channels = 8
cooperative_engagement = true
decoy_count = 16
torpedo_decoy = "AN/SLQ-25 Nixie"
towed_torpedo_decoy = true
Expand Down
1 change: 1 addition & 0 deletions data/platforms/surface/usn_ffg_constellation.tres
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ sensor_ids = PackedStringArray("an_spy_6_v3", "captas_mk2", "an_slq_32")
mast_height_m = 26.0
aircraft_capacity = 2
fire_control_channels = 4
cooperative_engagement = true
decoy_count = 14
weapon_loadout = {"sm2_family": 16, "essm_family": 32, "nsm_strike_missile": 16, "ram_block2": 21, "mk110_57mm_gun": 200, "mk54_lwt": 6}
source_status = "PUBLIC: designation and broad role; see DATA_SOURCES.md. GAMEPLAY_ESTIMATE: all numeric values, signatures, loadouts, channels and sensor envelopes. Not an operational capability claim."
Expand Down
1 change: 1 addition & 0 deletions data/platforms/theatres/jmsdf_ddg_maya.tres
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ length_m = 170.0
displacement_t = 10250.0
aircraft_capacity = 1
vls_cells = 96
cooperative_engagement = true
default_air_wing = {"jmsdf_helo_sh60k": 1}
source_status = "PUBLIC: class identity, dimensions and broad fit; see docs/THEATRES_2027.md. GAMEPLAY_ESTIMATE: ranges, signatures, hit probability, damage, timings, magazines and detachments. A 2027 recognition model, not a capability claim."
Loading
Loading