diff options
| author | David Racine <bass_dr@hotmail.com> | 2026-06-24 12:24:19 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-06-24 16:24:19 +0000 |
| commit | 8cf4ff5f141c78910f64d49213125fd661a559d2 (patch) | |
| tree | 8ad96f6a7022cf068157e5cf2fc1d224cde5381b /soh/src/code | |
| parent | 4a875dca4170f8a21b3e043d1bfb3d10d90e5822 (diff) | |
fix: free look continues from forced view when leaving a fixed camera (#4953) (#6808)
When a scene-forced/fixed camera (e.g. the Spirit Temple boulder-room
alcoves, CAM_SET_PREREND_FIXED / Camera_Fixed3) drives the view, the Free
Look angles in play->camX/camY are left untouched while manualCamera stays
set. On exit, Camera_Free resumed from those stale pre-alcove angles, so
the camera snapped/reversed instead of following the player out.
This does NOT change the forced-camera behavior: the alcove still clamps
exactly as the game intends. It only fixes the hand-off back to Free Look:
when Camera_Free resumes after another camera function drove the previous
frame (detected via a frame-number gap), the free-look yaw/pitch are
re-seeded from the camera's current orientation so the view continues from
where it was left.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'soh/src/code')
| -rw-r--r-- | soh/src/code/z_camera.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 71e4629c2..75297c546 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1450,6 +1450,20 @@ s32 Camera_Free(Camera* camera) { Parallel1* para1 = (Parallel1*)camera->paramData; f32 playerHeight; + // SOH [Enhancement] If free-look is resuming after a scene-forced/fixed camera drove the view + // (Camera_Free didn't run last frame while manualCamera stayed set, e.g. exiting a Spirit Temple + // alcove), re-seed the free-look angles from the camera's current orientation so the view continues + // from where it was left instead of snapping back to the pre-interruption angle. + static s32 sFreeLastFrame = 0; + s32 curFrame = camera->play->state.frames; + if (curFrame - sFreeLastFrame > 1) { + VecSph eyeAdjustment; + OLib_Vec3fDiffToVecSphGeo(&eyeAdjustment, &camera->at, &camera->eye); + camera->play->camX = eyeAdjustment.yaw; + camera->play->camY = eyeAdjustment.pitch; + } + sFreeLastFrame = curFrame; + at->x = Camera_LERPCeilF(camera->player->actor.world.pos.x, camera->at.x, 0.5f, 1.0f); at->y = Camera_LERPCeilF(camera->player->actor.world.pos.y + (camera->player->rideActor != NULL ? Player_GetHeight(camera->player) / 2 |
