ShieldManager's fallback (no ShieldEnvelope yet, e.g. every ship prefab
before the operator hand-rigs it per Q5) hard-failed to a fixed
Vector3.forward direction with a per-hit Debug.LogError. That silently
changed behaviour for every ship in the game until the operator edits
Longinus.prefab/Djinni.prefab on their own schedule -- worse than either
the deleted code or a loud one-time failure.
Extract ShieldEnvelope's local-direction primitive into two static,
no-component-required entry points -- SurfaceDirection(Transform, Vector3)
and LegacyLocalSurfacePoint(Transform, Vector3) -- so both FieldDriver's and
ShieldManager's fallbacks go through one owner instead of each re-deriving
the pre-Cut-2 formula by hand. ShieldManager's fallback now reproduces the
deleted normalize(shield.transform.InverseTransformPoint(point)) formula
exactly via the shared static, logging once (a warning, not a per-hit
error). FieldDriver's fallback is rewired onto the same static rather than
its own inline copy of the maths.
Documented, not silently assumed: FieldDriver's "envelope present" branch
(envelope.ProjectToSurface, world-space) and its fallback (the legacy local-
space formula) are only numerically identical when the carrier's transform
has zero position and identity rotation -- true of the one FieldDriver
carrier in the tree today, not true in general. This is a characteristic of
Cut 2 as scoped by the map (FieldDriver.cs:125 reads envelope.ProjectToSurface
directly, per the map's own text), not something this fix introduces or
resolves; flagged so nobody assumes the two branches are interchangeable for
a future non-origin, non-identity FieldDriver carrier.
ShieldPanelCut2Verify.CheckLegacyFallbackFormulas pins both static entry
points against an independent re-derivation of the exact pre-Cut-2 formulas,
on a carrier with a non-trivial transform (nonzero position, non-identity
rotation) so the check isn't vacuous. mutation_tests_shield_panel_cut2.py
gained two cases: SurfaceDirection collapsing back to a fixed Vector3.forward
(the exact regression fixed here), and LegacyLocalSurfacePoint collapsing to
the raw, untransformed world point -- both correctly fail the probe.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>