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:
parent
927fa7881a
commit
33cc9aa16a
5 changed files with 159 additions and 14 deletions
77
docs/research/2026-07-11-combat-target-camera-pseudocode.md
Normal file
77
docs/research/2026-07-11-combat-target-camera-pseudocode.md
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# Retail combat target camera pseudocode
|
||||
|
||||
Source: Sept 2013 EoR named retail client.
|
||||
|
||||
- `ClientCombatSystem::UpdateTargetTracking` (`0x0056A950`)
|
||||
- `ClientCombatSystem::TrackTarget` (`0x0056AED0`)
|
||||
- `CameraSet::TrackTarget` (`0x00458280`)
|
||||
- `CameraSet::SetTargetForOffset` (`0x004576E0`)
|
||||
- `CameraManager::SetTargetObject` (`0x00456380`)
|
||||
- `CameraManager::UpdateCamera` (`0x00456660`)
|
||||
|
||||
## Option consumer
|
||||
|
||||
```text
|
||||
UpdateTargetTracking():
|
||||
if ViewCombatTarget is enabled
|
||||
and combat mode is Melee or Missile
|
||||
and current attack target is valid:
|
||||
camera.TrackTarget(attackTarget)
|
||||
else:
|
||||
camera.TrackTarget(0)
|
||||
```
|
||||
|
||||
## Camera state
|
||||
|
||||
```text
|
||||
CameraSet.TrackTarget(targetId):
|
||||
if targetId != 0:
|
||||
targeting = true
|
||||
camera.SetTargetObject(targetId, wholeObject)
|
||||
camera.targetOffset = (0, 0, 0.5 metres)
|
||||
else:
|
||||
targeting = false
|
||||
|
||||
SetTargetForOffset(camera.viewerOffset)
|
||||
|
||||
SetTargetForOffset(viewerOffset), while targeting:
|
||||
camera.targetStatus = LOOK_AT_OBJECT | LOOK_AT_PIVOT
|
||||
```
|
||||
|
||||
## Per-frame pose
|
||||
|
||||
```text
|
||||
pivot = player part position + transformed pivotOffset
|
||||
direction = zero
|
||||
|
||||
if targetStatus contains LOOK_AT_OBJECT and target object exists:
|
||||
targetPoint = target.position localToGlobal targetOffset
|
||||
direction += normalize(targetPoint - pivot)
|
||||
|
||||
headingFrame = frameWhoseForwardIs(direction)
|
||||
desiredEye = pivot + headingFrame.transformVector(viewerOffset)
|
||||
|
||||
if targetStatus contains LOOK_AT_PIVOT:
|
||||
desiredForward = normalize(pivot - desiredEye)
|
||||
|
||||
damp current viewer toward (desiredEye, desiredForward)
|
||||
```
|
||||
|
||||
The target therefore changes the direction of the boom around the player; it
|
||||
does not replace the player as the boom's pivot. `LOOK_AT_PIVOT` keeps the
|
||||
player centered while the target-facing boom keeps the combat target in view.
|
||||
|
||||
## Port mapping
|
||||
|
||||
- `GameWindow.GetCombatCameraTargetPoint` applies the option/mode/valid-target
|
||||
gates and transforms the target-local 0.5 metre Z offset.
|
||||
- `RetailChaseCamera.ComputeTrackedHeading` ports the pivot-to-target direction.
|
||||
- Existing `RetailChaseCamera` boom construction and damping consume that
|
||||
heading unchanged.
|
||||
- The diagnostic legacy `ChaseCamera` remains intentionally non-retail under
|
||||
existing divergence row TS-19; the production retail camera owns this behavior.
|
||||
|
||||
The ACE and ACME reference trees are not present in this worktree (only the
|
||||
in-tree WorldBuilder reference is available), so no interpretation-aid cross
|
||||
check was possible. The named retail functions above are complete for this
|
||||
behavior and remain the ground truth.
|
||||
Loading…
Add table
Add a link
Reference in a new issue