diff --git a/soh/soh/Enhancements/camera/FreeLookDoorCamRelease.cpp b/soh/soh/Enhancements/camera/FreeLookDoorCamRelease.cpp new file mode 100644 index 0000000000..b742ba8aee --- /dev/null +++ b/soh/soh/Enhancements/camera/FreeLookDoorCamRelease.cpp @@ -0,0 +1,26 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/controls/Mouse.h" +#include "soh/ShipInit.hpp" + +#include + +extern "C" { +#include "global.h" +} + +void RegisterFreeLookDoorCamRelease() { + COND_VB_SHOULD(VB_RELEASE_DOORC_CAMERA, CVarGetInteger(CVAR_SETTING("FreeLook.Enabled"), 0), { + Camera* camera = va_arg(args, Camera*); + + // Also release the door peek camera when free look moves it, reusing SetCameraManual's threshold. + f32 freeLookX = -camera->play->state.input[0].cur.right_stick_x * 10.0f; + f32 freeLookY = camera->play->state.input[0].cur.right_stick_y * 10.0f; + Mouse_HandleThirdPerson(&freeLookX, &freeLookY); + + if (fabsf(freeLookX) >= 15.0f || fabsf(freeLookY) >= 15.0f) { + *should = true; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterFreeLookDoorCamRelease, { CVAR_SETTING("FreeLook.Enabled") }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 87ef445e56..db841e8745 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2083,6 +2083,13 @@ typedef enum { VB_RED_ICE_MELTED_FLAG, // #### `result` + // ```c + // camera->xzSpeed > 0.001f || || params->interfaceFlags & 0x8 + // ``` + // #### `args` + // - `Camera*` (`camera`) + VB_RELEASE_DOORC_CAMERA, + // #### `result` // ```c // true diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index af665014d7..71e4629c2e 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -6921,14 +6921,19 @@ s32 Camera_Special9(Camera* camera) { camera->unk_14C |= (0x400 | 0x10); sCameraInterfaceFlags = 0; - if (camera->xzSpeed > 0.001f || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_A) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_B) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CLEFT) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CDOWN) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CUP) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CRIGHT) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_R) || - CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_Z) || params->interfaceFlags & 0x8) { + // SOH [Enhancement] VB_RELEASE_DOORC_CAMERA lets free look hand the door peek camera + // back on right-stick input (see soh/Enhancements/camera/FreeLookDoorCamRelease.cpp). + if (GameInteractor_Should( + VB_RELEASE_DOORC_CAMERA, + camera->xzSpeed > 0.001f || CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_A) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_B) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CLEFT) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CDOWN) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CUP) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_R) || + CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_Z) || params->interfaceFlags & 0x8, + camera)) { Camera_ChangeSettingFlags(camera, camera->prevSetting, 2); camera->unk_14C |= (0x4 | 0x2);