Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

164 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Spectator controls and recovery
While spectating, **Left / Right arrow** selects an eligible teammate or player
corpse. **Enter** (including numpad Enter) toggles between orbit and the living
teammate's sampled camera position, orientation and field of view. Orbit retains
mouse-look and zoom. This is presentation only: no teammate is possessed.
`/esc spectate next|previous` remains available without administrator permission.
If nobody is available to follow, mouse-look and zoom still orbit the casualty's
position (or the last known observer anchor), with a 2–12 metre zoom range. This includes
playing alone, an all-unconscious squad, and a selected entity that has not yet
streamed in. The camera stays anchored; it does not move the body or allow free
flight. Menus and chat continue to pause camera input.
When the teammate uses a compatible native PiP scope, spectator first-person
view renders the magnified image inside the visible 3D optic, with the player's
eye view around it. Both the watched player and spectator must have **2D scopes
disabled** in their game settings. The watched player must actually be using
PiP; a flat source view cannot supply the second camera.
Standard 2D optics, unsupported PiP materials, a spectator's 2D preference or
failed PiP setup retain the full-screen scope view, including the authored
reticle, sampled magnification, zeroing and illumination. Iron sights and
ordinary first-person poses keep the existing camera relay. Unrelated custom
scope renderers are not automatically reproduced.
Both camera poses and lens state travel in one bounded, authorized packet.
Eye and aiming poses are interpolated on matching timelines; PiP FOV, parallax
and lens shading use the aiming timeline too. Displayed weapon identity and
sight index must match the streamed target. No spectator ADS callbacks, weapon
input registration or remote zoom changes are invoked. Only the full-screen
fallback hides/restores the local weapon/optic rendering. PiP uses the native
local lens-rendering lifecycle and leaves the weapon visible. Switching targets,
leaving player view, death/recovery, a displaced camera or expired samples closes
the renderer. Failed setup retries are limited to once every two seconds.
PiP adds a second scene render on the spectator's computer. This implementation
passed focused packet/interpolation/lifecycle checks and a hidden Reforger 1.8
Workbench compile. Multiplayer visual alignment, addon-specific materials and
FPS impact remain in-game validation items; these have not been established by
the earlier camera fixture runs described below.
Samples expire after 350 ms; stale or missing views fall back to orbit rather
than showing a stale scope. Changing between scope and ordinary view snaps to
the new camera sample, avoiding interpolation through the weapon. Same-view
updates retain the existing short interpolation.
The camera activates `ERR_ObserverContext`, inherited from vanilla's manual-camera context. Dedicated input actions bind the arrows and Enter; normal gameplay input remains inherited from `chimeraInputCommon.conf`. Held keys trigger once; opposing arrows cancel. Camera input is disabled while ordinary menus/dialogs are open. These controls replace raw `Debug.KeyState` polling; the old bit-15 mask is documented by the engine, so inspection alone does not establish it as the cause of the reported missed arrows.
Chat's explicit open state now takes priority before the observer activates its
camera context. The observer renews native `ChatContext` for open registered
panels, and for a still-open panel found through the focused widget's parents if
the HUD has unregistered it. This keeps submission available even without the
usual HUD update. Ordinary edit/password fields and native menus still pause the
camera; only actual open chat renews chat input. Closing chat retains the existing
release requirement, so holding Enter or an arrow through submission cannot
immediately switch view or teammate. Installed defaults open chat with Slash and
send with Enter; no bindings change.
This addresses a possible input failure reported during corpse observation.
Native `#login` uses the controller's chat component, independently of the mod's
`/esc` commands and body state. Available client logs do not record whether the
historical login command was submitted, so the cause of that attempt remains
unconfirmed. This change neither grants administrator rights nor changes login
handling. [Input handoff evidence](evidence/observer-chat-2026-10-13/README.md).
The 250 ms local monitor records an unconscious controlled body independently of whichever camera is active. When that same body becomes conscious, it asks the native editor manager (Game Master/ArmaVision) to close and explicitly selects the controller's player camera. This also handles a separate manual camera taking over from the mission's observer camera. Asynchronous editor closure or unavailable player cameras are retried for up to ten seconds; refusal is logged rather than permanently forcing the camera. Once returned, conscious admins can open their cameras normally. Round end, body loss, or changed possession cancels the pending handoff. No remote player is possessed and no administrative privileges change.
The spectator hint explains why the player is observing and how to switch targets/views. Availability uses the replicated selected entity ID, not local streaming completion. The hint refreshes on first display, a reason change, or having/no selected survivor; stable state does not repeatedly show it. Missing/refusing hint managers retain the retry.
## Verification
`test_observer_orbit.py`, `test_unconscious_controls.py`, `test_spectator_recovery.py`, `test_spectator_guidance.py`, `test_hint_delivery.py`, and `test_participant_selection.py` exercise production orbit placement/input with and without a target, held/opposing/menu keys, Enter toggling, camera/editor recovery retries and cancellation, guidance, and canonical server selection. Native APIs and remote clients are doubled in these tests.
`ERR_UnconsciousCameraProbe` tests native incapacitation, unchanged possession, physical camera tracking, loaded input actions including inherited orbit input, toggling to/from head view, a different manual camera taking over before healing, return to the normal camera, and repeated knockout. It uses a physical stand-in for another player and programmatic input-handler calls; it does not prove physical keyboard delivery or dedicated multiplayer target streaming. Native run results are recorded separately under `.local/analysis/spectator-2026-09-27/`.
On 13 October, the anchor-only camera fix passed 38 native assertions, including
seven new checks for yaw, pitch, zoom, disabled input, unchanged possession and
application of the resulting pose on subsequent native frames. Previously, all
orbit input and placement were inside the selected-entity branch, so a solo
casualty or all-unconscious squad without a corpse to follow had a fixed view.
The behavioral regression fails on that original branch and passes on the fix.
The native test supplies action values; physical mouse delivery and multiplayer
remain unverified. The isolated run moves only the legacy test pickup marker to
flat ground so unrelated rescue-fleet preparation can finish. There were no
script/runtime failures; 21 inherited engine/resource errors still fail the
strict native report. The full repository check remains blocked by the existing
missing root entity ID in `ERRM_AtlasLeaf.et`.
[Evidence and limitations](evidence/observer-orbit-2026-10-13/README.md).
On 27 September, the isolated native fixture completed 25 assertions without script errors or VM exceptions. It verified both camera views, the loaded controls, a separate manual camera takeover, restoration after healing, and repeated knockout. The runner subsequently hit a transient cleanup-classification failure; separate follow-up confirmed the private runtime idle and authored sources unchanged. Existing external resource errors remain. Raw results and failed diagnostic iterations are preserved in the evidence directory above. Physical keyboard delivery, remote client cycling, and native Game Master/ArmaVision menu closure remain manual multiplayer checks.
## Sideways-drift investigation, 29 September 2026
The reported first-person drift is not yet reproduced. Temporary diagnostics
compared the normal local first-person camera with `PlayerView` through scripted
aim changes and a stationary hold. The [aim comparison](evidence/native-2026-09-29-camera-aim-diagnostic/report.json)
and [position comparison](evidence/native-2026-09-29-camera-position-diagnostic/report.json)
both completed the existing 25 camera/recovery assertions with no script/runtime
failures, unchanged launch sources and confirmed cleanup. Existing inherited
asset errors remain in the reports.
Across the second run's 26 samples the forward vectors matched to logged
precision; viewpoint position differed because spectator view is offset ahead
of the animated head. This does not establish the cause of the user's drift.
Attempts to exercise freelook and leaning through one-shot input-context setters
did not hold those states (the trace remained at zero lean), so those cases and
remote-player replication remain unverified. The temporary probe is retained as
`diagnostic-probe.c.txt` in the second archive and removed from the active addon.
Those initial diagnostic runs did not change production camera behavior. The
user subsequently clarified that the symptom affects teammate first-person view,
possibly sliding left and later over the shoulder.
Inspection found a concrete fallback bug: a failed head-pose read fell through
to orbit placement and orbit mouse/zoom input even with player view selected.
The camera now caches the last valid pose in target-local space, preventing this
fallback after tracking has begun. This fixes a plausible path to the reported
shoulder view; it does not establish that a missing pose caused the user's exact
multiplayer symptom. Animated head sway remains, including genuine leaning.
The production cache regression exercises body translation/rotation, 1,000
missing samples without accumulating movement, fresh-pose recovery, target
changes and target loss. The native fixture now deliberately withholds head
samples while moving its physical stand-in, then restores them and checks that
head tracking resumes before returning to orbit. This is an injected sampling
gap, not a reproduced network outage.
The [final engine run](evidence/native-2026-09-29-camera-gap-fixed/report.json)
passed all 27 camera/recovery assertions, including the moving-target pose gap
and resumed head tracking. Repository checks passed. Addon sources remained
unchanged during the run and cleanup was confirmed; no script/runtime failures
occurred. The strict report retains 13 inherited asset errors. An earlier
[test-hook registration failure](evidence/native-2026-09-29-camera-gap-fixture-diagnostic/report.json)
is retained; fault injection now lives behind the explicit Workbench fixture
flag without modding the prefab component's registration. A separate
[pose diagnostic](evidence/native-2026-09-29-camera-pose-diagnostic/report.json)
also exercised sustained native leaning without reproducing angular drift;
its freelook input did not activate, so freelook remains unverified.
No Workshop publication or live-server update was performed.
### Observer monitor ownership (2 October 2026)
A retained former local controller now stops its observer callback before it can restore its old player camera, close the editor or spawn a spectator camera for the new local session. It clears only its own timer, pending recovery state and owned observer camera. The current controller's timer and view remain intact; the existing 250 ms binder now remains active until stop/end so a replacement controller starts its monitor once. Repeated checks do not create extra timers. Native manual-camera teardown retains its ordinary previous-camera fallback when the deleted camera itself is current.
An actual-method regression independently reproduces the old camera/editor change and passes with the guard. All **279 registered regression programs pass**. The [hidden/muted native fixture](evidence/native-2026-10-02-observer-ownership/report.json) completes **27 assertions and one round** for ordinary unconsciousness, target tracking, both views, a head-pose sampling gap, healing and repeated knockout. It has zero script/runtime failures and thirteen retained installed-resource errors, with unchanged source/external inputs and confirmed cleanup. The initial wrong-selector failure is preserved; `unconscious-camera` now requires `--project core` before runtime setup. Native controller replacement, shared input internals and real multiplayer remain unqualified. This correction does not establish the cause of the previously reported first-person drift. [Review and preservation](evidence/observer-ownership-2026-10-02/review.json).
## Recovery warnings while unconscious (2 October 2026)
The ordinary phase guide intentionally yields to spectator presentation. The observer now appends the existing replicated `RecoveryStatus`, so an unconscious player receives the same treatment/natural-recovery, possible returning rescuer, or uninterrupted thirty-second medical-defeat warning that conscious players can read in objective details. Medical policy and timing are unchanged.
The accepted status joins reason and survivor availability in hint deduplication. A missing hint manager or rejected delivery does not consume the message; an unchanged accepted message does not repeat. Waking, end-of-round cleanup and old-controller ownership checks preserve the existing camera behavior and clear only the owning controller's cache.
An actual-method regression fails on the earlier missing-warning behavior and passes with the fix, including status changes, delivery retries and round/controller replacement. The [native camera fixture](evidence/native-2026-10-02-recovery-warning/report.json) accepts the real ongoing-treatment status and clears it on awakening while retaining the earlier camera/recovery checks: 29 assertions, zero script failures and thirteen retained engine errors. This proves the accepted hint path, not full-resolution readability or remote multiplayer presentation. [Review and exact source scope](evidence/recovery-launcher-2026-10-02/review.json).
## Dead-player selection (6 October 2026)
Camera cycling includes canonical player corpses alongside surviving teammates,
not only after the last survivor dies. It includes the observer's own body and
bodies whose player has disconnected. Loss of native controller or faction
association during corpse cleanup does not remove the round-roster identity.
Deleted bodies and known foreign-faction bodies remain excluded. A selected
corpse stays selected during ordinary polling until the player cycles or the
body is removed.