diff --git a/patches/camera_patches.c b/patches/camera_patches.c index a1d0075..c13ab82 100644 --- a/patches/camera_patches.c +++ b/patches/camera_patches.c @@ -8,6 +8,7 @@ static bool prev_analog_cam_active = false; static bool can_use_analog_cam = false; static bool analog_cam_active = false; +static bool analog_cam_skip_once = false; VecGeo analog_camera_pos = { .r = 66.0f, .pitch = 0, .yaw = 0 }; @@ -62,6 +63,11 @@ void update_analog_cam(Camera* c) { analog_cam_active = true; } + if (analog_cam_skip_once) { + analog_cam_active = false; + analog_cam_skip_once = false; + } + // Record the Z targeting state. prev_targeting_held = targeting_held; @@ -1873,3 +1879,18 @@ void analog_cam_post_play_update(PlayState* play) { active_cam->inputDir.y = analog_camera_pos.yaw + DEG_TO_BINANG(180); } } + +bool get_analog_cam_active() { + return analog_cam_active; +} + +void set_analog_cam_active(bool isActive) { + analog_cam_active = isActive; +} + +// Calling this will avoid analog cam taking over for the following game loop. +// E.g. using left stick inputs while in a deku flower taking priority over right stick. +void skip_analog_cam_once() { + analog_cam_skip_once = true; + analog_cam_active = false; +} diff --git a/patches/input.c b/patches/input.c index 03cbc47..c128c63 100644 --- a/patches/input.c +++ b/patches/input.c @@ -2527,3 +2527,65 @@ void AudioOcarina_CheckSongsWithoutMusicStaff(void) { } } } + +extern s32 Player_GetMovementSpeedAndYaw(Player* this, f32* outSpeedTarget, s16* outYawTarget, f32 speedMode, + PlayState* play); +extern bool get_analog_cam_active(); +extern void skip_analog_cam_once(); + +// @recomp Updates yaw while inside of deku flower. +void func_80855F9C(PlayState* play, Player* this) { + f32 speedTarget; + s16 yawTarget; + + this->stateFlags2 |= PLAYER_STATE2_20; + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, 0.018f, play); + + // @recomp If left stick inputs are occurring, prevent analog cam. + if ((play->state.input[0].rel.stick_y != 0 || play->state.input[0].rel.stick_x != 0)) { + skip_analog_cam_once(); + } + + if (get_analog_cam_active()) { + // @recomp set current yaw to active camera's yaw. + this->currentYaw = Camera_GetInputDirYaw(GET_ACTIVE_CAM(play)); + } else { + Math_ScaledStepToS(&this->currentYaw, yawTarget, 0x258); + } +} + +extern void set_analog_cam_active(bool isActive); +extern void Player_Action_4(Player* this, PlayState* play); +extern s32 Player_SetAction(PlayState* play, Player* this, PlayerActionFunc actionFunc, s32 arg3); +extern LinkAnimationHeader gPlayerAnim_pg_maru_change; + +s32 func_80857950(PlayState* play, Player* this) { + // @recomp track if newly going from non-spike roll to spike roll (spike rolling when this->unk_B86[1] == 1) + static bool wasOff = true; + bool isOff = this->unk_B86[1] == 0; + if (wasOff && !isOff) { + // @recomp set analog cam to be active now that rolling has started + set_analog_cam_active(false); + } + wasOff = isOff; + + // @recomp Manual relocation, TODO remove when automated. + Input* player_control_input = *(Input**)KaleidoManager_GetRamAddr(&sPlayerControlInput); + + if (((this->unk_B86[1] == 0) && !CHECK_BTN_ALL(player_control_input->cur.button, BTN_A)) || + ((this->av1.actionVar1 == 3) && (this->actor.velocity.y < 0.0f))) { + + // @recomp Manual relocation, TODO remove when automated. + PlayerActionFunc Player_Action_4_reloc = KaleidoManager_GetRamAddr(Player_Action_4); + Player_SetAction(play, this, Player_Action_4_reloc, 1); + + Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.prevPos); + PlayerAnimation_Change(play, &this->skelAnime, &gPlayerAnim_pg_maru_change, -2.0f / 3.0f, 7.0f, 0.0f, + ANIMMODE_ONCE, 0.0f); + Player_PlaySfx(this, NA_SE_PL_BALL_TO_GORON); + wasOff = true; + return true; + } + + return false; +}