Fix convoy coordination, AI combat and spectator recovery

This commit is contained in:
2026-09-27 22:28:07 +02:00
parent 2551d171b3
commit c5629f7f4f
108 changed files with 4337 additions and 282 deletions
+13 -5
View File
@@ -1,9 +1,17 @@
# Spectator reason and controls
# Spectator controls and recovery
The local observer hint now explains the replicated reason for spectating: the player has used their round's life, joined after extraction began, or could not be spawned. It tells a spectator with a selected survivor about the existing `/esc spectate next` and `/esc spectate previous` commands. Those commands already use the ordinary nonadministrator path; the change does not grant administration, change spawn/identity policy or alter camera control.
While spectating, **Left / Right arrow** selects the previous/next eligible teammate. **Enter** (including numpad Enter) toggles between the orbit camera and a player view at the teammate's head, looking along their replicated head-aim direction. Orbit retains mouse-look and zoom. Player view follows posture and vehicle seating; it does not possess the teammate, reproduce their private HUD/ADS camera, or move the unconscious body. With no available/streamed target the camera falls back to the observer anchor. `/esc spectate next|previous` remains available without administrator permission.
When the server has selected no survivor, the hint says that nobody is currently available to follow and that the view will follow a survivor when one becomes available. It omits ineffective cycling advice in that state. Availability is read from the replicated selected entity ID, not from whether that entity has finished streaming to this client, so streaming delay is not mistaken for an empty survivor set.
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.
The existing 250 ms observer monitor refreshes the twelve-second hint on first display, a reason change or a change between having/no selected survivor. Stable state does not repeat hints, and switching between two available survivors does not produce another hint. Closing the camera clears the shown flag. If the native hint manager is temporarily absent, the monitor retries without consuming the first display. There are no new timers, input bindings, RPCs, permission checks or server mutations.
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.
`tests/test_spectator_guidance.py` executes the actual message and refresh methods for every current reason, a fallback reason, both availability states and all prior/current refresh combinations. It also checks the existing monitoring/command boundaries: no extra timer, state recorded only after a hint exists, close/reopen reset, cycling handled before the admin transport and unchanged admin rejection. These are source-local policy and integration-contract checks. Native compilation, real hint rendering, actual chat input and remote target streaming still require their own tests.
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_unconscious_controls.py`, `test_spectator_recovery.py`, `test_spectator_guidance.py`, `test_hint_delivery.py`, and `test_participant_selection.py` exercise production input dispatch, 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 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.