fix(combat): track targets with retail camera

Port ClientCombatSystem's Keep in View consumer through CameraSet's pivot-to-target boom heading, including the transformed half-metre target offset and melee/missile validity gates. Preserve the existing stateful chase damping and collision architecture, with conformance coverage and named-retail pseudocode.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-11 20:36:58 +02:00
parent 927fa7881a
commit 33cc9aa16a
5 changed files with 159 additions and 14 deletions

View file

@ -116,6 +116,31 @@ public class RetailChaseCameraTests
// ── Basis from heading ────────────────────────────────────────────
[Fact]
public void TrackedHeading_UsesPivotToRetailTargetOffsetPoint()
{
// The target is ten metres east and one metre below the player's
// 1.5 metre camera pivot after TrackTarget's 0.5 metre offset.
var pivot = new Vector3(0f, 0f, 1.5f);
var targetPoint = new Vector3(10f, 0f, 0.5f);
Vector3 expected = Vector3.Normalize(new Vector3(10f, 0f, -1f));
Vector3 heading = RetailChaseCamera.ComputeTrackedHeading(pivot, targetPoint)!.Value;
Assert.Equal(expected.X, heading.X, 5);
Assert.Equal(expected.Y, heading.Y, 5);
Assert.Equal(expected.Z, heading.Z, 5);
}
[Fact]
public void TrackedHeading_MissingOrCoincidentTarget_FallsBack()
{
var pivot = new Vector3(1f, 2f, 3f);
Assert.Null(RetailChaseCamera.ComputeTrackedHeading(pivot, null));
Assert.Null(RetailChaseCamera.ComputeTrackedHeading(pivot, pivot));
}
[Fact]
public void Basis_HorizontalHeading_IsOrthonormalAndRightHanded()
{