Repository navigation
fix(input): reseed mouse look after camera handover - #2653
Conversation
Invalidate the retained angle target when the player camera is inactive. This restores the existing handover contract after NotRexed#2617 without removing persistent angles while active. Cover pitch and yaw when returning to both active states. Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <noreply@openai.com>
hckrman101
left a comment
There was a problem hiding this comment.
Thanks, this is the right fix. I traced it on main: the free-look guard clears target_ok just before the slingshot block, the state(4) frame reseeds from yaw 5, and then the state-0 branch returned without dropping that target, so the first frame back turned from 5 instead of the game's 0 (yaw 4, the CI failure). Clearing it in the not-3/4 branch closes that.
What I checked:
- Every way back from a non-3/4 state now reseeds yaw and pitch from the game's current angles before the frame's motion is added, so there's no jump on the first frame back. Going 3 to 4 or 4 to 3 doesn't touch it (the stick path still reseeds), and a camera that stays in 3/4 the whole time behaves exactly as before; the no-drift checks still cover that.
- The loop is a real test both times through: on the first pass the stale target would be yaw 5 / pitch 10, on the second -1 / 20.5, and both differ from the 0 / 20 the game sets, so a stale yaw or pitch fails either way back (3 and 4).
One thing for a follow-up, not this PR: the reseed only happens when the hook runs in another state. If the player camera's update stops running altogether (the pause menu, a scene load) and the camera comes back at the same address in state 3 with new angles, target_ok is still 1 and the old target gets written over them. I haven't checked in game whether that happens. If it does, the fix is just as small: reseed when the hook hasn't run within LIVE_NS (read last_hook_ns before it's overwritten).
Python checks are still running; the rest is green.
Upstream NotRexed/Hookshot 0ec31ff (NotRexed#2653): NotRexed#2617 kept the mouse's target angles to stop the follow camera drifting the view, but the guard for a camera the mouse does not own returned without invalidating them. After a first-person aim or another camera, the next player camera applied the mouse's motion to the old yaw (5) instead of the game's current one (0). Ported into host/mouse_native.c: clear target_ok while the camera is in any state but 3 or 4, so the next player-camera frame seeds yaw and pitch from the game's current angles. Immediate stick handback and the held angles while the camera is active are unchanged. readme.md's Mouse camera entry describes the handover. Test: tests/mouse_native_test.c now returns from a first-person camera (state 0) to both 3 and 4 with the same movement, checking the new yaw (-1) and pitch (20.5) come from the game's current view, and that hos_mouse_native reports the camera again. built and run by builder/rust/tests/host_c_fixtures.rs (POSIX only); it skips without a C compiler. No game, mouse or Windows run was made. Assisted-by: opencode (DeepSeek V4.1 Flash 1017)
…seeded, V-Sync Auto with DLSS Frame Gen, NotRexed#2746) Upstream fixed most of what e3f076a fixed here (NotRexed#2648, NotRexed#2651, NotRexed#2652, NotRexed#2653, NotRexed#2654, NotRexed#2661), so the conflicts are resolved to upstream's versions: its fixtures, its menu_i18n.h, its mouse_native.c, and its dlss_checks.h with the two-pixel tolerance it chose and tests. Kept from the fork: the fixtures' framegen_by_pick stand-in, and vk_texture.cpp's typed min. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
What this is for: resume Native mouse look from the game's current camera angles after another camera takes over (current main CI). What is measured: the affected game-free check before and after, with GCC 16.2.1 and Clang 23.1.3 selected, plus one strict full-suite run, as recorded below. Not measured: a game run or Windows execution.
Cause
#2617 retains mouse target angles to prevent drift, but the existing inactive-state guard returns without invalidating that target; the pre-existing handover test then applies movement to old yaw 5 instead of current yaw 0 (
host/mouse_native.c:120-148,tests/test_mouse_native.py).The relevant failure in main's CI log is:
What changed
Clear
target_okwhen the player camera is inactive; keep immediate stick handback and persistent angles while active. Preserve the original failing yaw assertion, exercise changed pitch and yaw on return to both active states, and document the handover in the readme.How it was tested
Recorded on 2026-11-11, Linux kernel
7.2.15-1-omarchy, basede866017, head58c817f7(version and test records).a016b7a6: the affected check fails independently in both compiler environments with the diagnostic above; the branch passes independently in both (python -I -B tests/run_all.py --strict --jobs 1 tests/test_mouse_native.pyrecords).python -I -B tests/run_all.py --strict:456 passed, 14 failed, 20 skipped in 178 s (linux, 32 at once), load 33.42 → 81.38 (complete suite output).test_wayland_libdecor_hint.py,test_display_startup_failure.py,test_texel_buffer_ownership.py,test_audio_aux.py,test_audio_biquad.py,test_dlss_checks.py,test_env_on.py,test_framegen_preset.py,test_hdr_encode.py,test_linux_docker_packages.py,test_menu_i18n.py,test_mods_size_table.py,test_readback_part.py,test_rumble_menu.py(complete suite output). The companion fixture, capture-switch, PPA-parser and hint-catalog branches address their separate causes; feat(vk): FSR 3.1 on the chain keeps the game's native HDR highlights #2614 owns the HDR check and is not duplicated here.Not tested / risks
The executable fixture runs the actual camera function against authored state, but no game, real mouse/controller, Windows or camera-transition playtest was run.
Overlaps
The inspected #2567 first-person changes and #2630 camera-centering restoration do not contain this handover fix and merge cleanly in the recorded comparison.
Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra noreply@openai.com