Add API function export for camera Z-targeting fixes (#503)
This commit is contained in:
parent
2ed55b4ff2
commit
552a82b3b0
|
@ -9,6 +9,8 @@
|
|||
#include "z64shrink_window.h"
|
||||
#include "z64player.h"
|
||||
|
||||
static bool camera_fixes = false;
|
||||
|
||||
static bool prev_analog_cam_active = false;
|
||||
static bool can_use_analog_cam = false;
|
||||
static bool analog_cam_active = false;
|
||||
|
@ -26,6 +28,10 @@ float analog_camera_y_sensitivity = 500.0f;
|
|||
|
||||
static const float analog_cam_threshold = 0.1f;
|
||||
|
||||
RECOMP_EXPORT void recomp_set_camera_fixes(bool new_val) {
|
||||
camera_fixes = new_val;
|
||||
}
|
||||
|
||||
void update_analog_camera_params(Camera* camera) {
|
||||
// recomp_printf("Camera at: %.2f %.2f %.2f\n"
|
||||
// " eye: %.2f %.2f %.2f\n"
|
||||
|
@ -1064,6 +1070,10 @@ RECOMP_PATCH s32 Camera_Jump2(Camera* camera) {
|
|||
*/
|
||||
// @recomp Patched for analog cam.
|
||||
RECOMP_PATCH s32 Camera_Parallel1(Camera* camera) {
|
||||
// @recomp
|
||||
static bool prev_targeting_held = false;
|
||||
bool isChargingDekuFlowerDive = !!(((Player*)camera->focalActor)->stateFlags3 & PLAYER_STATE3_100);
|
||||
|
||||
Vec3f* eye = &camera->eye;
|
||||
Vec3f* at = &camera->at;
|
||||
Vec3f* eyeNext = &camera->eyeNext;
|
||||
|
@ -1089,6 +1099,10 @@ RECOMP_PATCH s32 Camera_Parallel1(Camera* camera) {
|
|||
CameraModeValue* values;
|
||||
f32 yNormal;
|
||||
|
||||
// @recomp Read timer4 from timer2.
|
||||
s16 timer4 = rwData->timer2 >> 5; // @recomp Used to check if z-target can be quit. Mirrors timer2 values during z-target in unmodified function.
|
||||
rwData->timer2 &= 0x001F;
|
||||
|
||||
if (!RELOAD_PARAMS(camera)) {
|
||||
} else {
|
||||
values = sCameraSettings[camera->setting].cameraModes[camera->mode].values;
|
||||
|
@ -1151,6 +1165,8 @@ RECOMP_PATCH s32 Camera_Parallel1(Camera* camera) {
|
|||
rwData->timer2 = 20;
|
||||
} else {
|
||||
rwData->timer2 = 6;
|
||||
// @recomp Initiate timer4 for z-target.
|
||||
timer4 = 6;
|
||||
}
|
||||
|
||||
if ((camera->focalActor == &GET_PLAYER(camera->play)->actor) && (camera->mode == CAM_MODE_CHARGE)) {
|
||||
|
@ -1187,12 +1203,55 @@ RECOMP_PATCH s32 Camera_Parallel1(Camera* camera) {
|
|||
rwData->unk_26 = 1;
|
||||
camera->animState = 1;
|
||||
sCameraInterfaceFlags = roData->interfaceFlags;
|
||||
|
||||
// @recomp Reset prev_targeting_held after transition.
|
||||
prev_targeting_held = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// @recomp Change behavior for z-target only.
|
||||
if (camera_fixes) {
|
||||
if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == PARALLEL1_FLAG_1) {
|
||||
Player* player = GET_PLAYER(camera->play);
|
||||
bool targeting_held = func_80123434(player) || player->lockOnActor != NULL;
|
||||
|
||||
// @recomp Fix camera rotating with player if z-target gets released too fast after transition.
|
||||
if ((targeting_held) && (!prev_targeting_held)) {
|
||||
// @recomp Reset timer2 to avoid immediate rotation, if player presses, releases and presses z-target in a very short time-window.
|
||||
rwData->timer2 = 6;
|
||||
rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22;
|
||||
}
|
||||
|
||||
// @recomp Maintain vanilla behavior for quitting z-target.
|
||||
if ((timer4 == 0) && (!targeting_held)) {
|
||||
rwData->timer2 = 0;
|
||||
}
|
||||
|
||||
// @recomp Decrease timer4 only in cases where timer2 would be decreased.
|
||||
if ((timer4 > 0)
|
||||
&& (rwData->timer3 <= 0)) {
|
||||
timer4--;
|
||||
}
|
||||
|
||||
prev_targeting_held = targeting_held;
|
||||
}
|
||||
}
|
||||
|
||||
if (rwData->timer2 != 0) {
|
||||
switch (roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) {
|
||||
case PARALLEL1_FLAG_1:
|
||||
if (camera_fixes) {
|
||||
// @recomp Fix camera rotating with player if z-target gets released too fast after transition.
|
||||
if (isChargingDekuFlowerDive) {
|
||||
// @recomp Fix camera wiggle during dive into deku flower.
|
||||
rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22;
|
||||
}
|
||||
rwData->unk_20 = roData->unk_20;
|
||||
break;
|
||||
}
|
||||
// @recomp fallthrough
|
||||
|
||||
case (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1):
|
||||
rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22;
|
||||
rwData->unk_20 = roData->unk_20;
|
||||
|
@ -1400,18 +1459,31 @@ RECOMP_PATCH s32 Camera_Parallel1(Camera* camera) {
|
|||
func_800CBFA4(camera, at, eye, 3);
|
||||
}
|
||||
|
||||
if (camera_fixes) {
|
||||
// @recomp Fix camera not updating input dir for the first few frames after transition.
|
||||
if ((isChargingDekuFlowerDive) && (rwData->timer2 != 0)) {
|
||||
// @recomp Fix camera wiggle during dive into deku flower.
|
||||
sUpdateCameraDirection = true;
|
||||
} else {
|
||||
sUpdateCameraDirection = false;
|
||||
}
|
||||
} else {
|
||||
if (rwData->timer2 != 0) {
|
||||
sUpdateCameraDirection = true;
|
||||
} else {
|
||||
sUpdateCameraDirection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
camera->fov = Camera_ScaledStepToCeilF(rwData->unk_08, camera->fov, camera->fovUpdateRate, 0.1f);
|
||||
camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5);
|
||||
camera->atLerpStepScale = Camera_ClampLerpScale(camera, sp72 ? roData->unk_1C : roData->unk_18);
|
||||
rwData->unk_26 &= ~1;
|
||||
|
||||
// @recomp Save timer4 in unused bits of timer2.
|
||||
rwData->timer2 |= timer4 << 5;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue