mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp.git
synced 2026-05-07 17:41:36 +00:00
Apply aiming inversion to telescope camera, allow right stick to be used for aiming when analog cam is enabled
This commit is contained in:
parent
d8f9a2e5c8
commit
cbd39ebb59
1 changed files with 157 additions and 11 deletions
168
patches/input.c
168
patches/input.c
|
|
@ -16,10 +16,27 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
|
||||||
// @recomp Get the aiming camera inversion state.
|
// @recomp Get the aiming camera inversion state.
|
||||||
s32 inverted_x, inverted_y;
|
s32 inverted_x, inverted_y;
|
||||||
recomp_get_inverted_axes(&inverted_x, &inverted_y);
|
recomp_get_inverted_axes(&inverted_x, &inverted_y);
|
||||||
|
// @recomp Get the analog camera input values if analog cam is enabled.
|
||||||
|
s32 analog_x = 0;
|
||||||
|
s32 analog_y = 0;
|
||||||
|
if (recomp_analog_cam_enabled()) {
|
||||||
|
float analog_x_float = 0.0f;
|
||||||
|
float analog_y_float = 0.0f;
|
||||||
|
recomp_get_camera_inputs(&analog_x_float, &analog_y_float);
|
||||||
|
// Scale by 127 to match what ultramodern does, then clamp to 60 to match the game's handling.
|
||||||
|
analog_x = (s32)(analog_x_float * 127.0f);
|
||||||
|
analog_x = CLAMP(analog_x, -60, 60);
|
||||||
|
analog_y = (s32)(analog_y_float * -127.0f);
|
||||||
|
analog_y = CLAMP(analog_y, -60, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
recomp_printf("stick_x: %d stick_y: %d analog_x: %d analog_y: %d\n",
|
||||||
|
play->state.input[0].rel.stick_x, play->state.input[0].rel.stick_y,
|
||||||
|
analog_x, analog_y);
|
||||||
|
|
||||||
if (!func_800B7128(this) && !func_8082EF20(this) && !arg2) {
|
if (!func_800B7128(this) && !func_8082EF20(this) && !arg2) {
|
||||||
|
// @recomp Add in the analog camera Y input. Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
var_s0 = play->state.input[0].rel.stick_y * 0xF0;
|
var_s0 = CLAMP(play->state.input[0].rel.stick_y + analog_y, -61, 61) * 0xF0;
|
||||||
|
|
||||||
// @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted).
|
// @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted).
|
||||||
if (!inverted_y) {
|
if (!inverted_y) {
|
||||||
|
|
@ -27,7 +44,9 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
|
||||||
}
|
}
|
||||||
Math_SmoothStepToS(&this->actor.focus.rot.x, var_s0, 0xE, 0xFA0, 0x1E);
|
Math_SmoothStepToS(&this->actor.focus.rot.x, var_s0, 0xE, 0xFA0, 0x1E);
|
||||||
|
|
||||||
var_s0 = play->state.input[0].rel.stick_x * -0x10;
|
// @recomp Add in the analog camera X input. Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
|
var_s0 = CLAMP(play->state.input[0].rel.stick_x + analog_x, -61, 61) * -0x10;
|
||||||
|
|
||||||
// @recomp Invert the X axis accordingly
|
// @recomp Invert the X axis accordingly
|
||||||
if (inverted_x) {
|
if (inverted_x) {
|
||||||
var_s0 = -var_s0;
|
var_s0 = -var_s0;
|
||||||
|
|
@ -76,7 +95,8 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
|
||||||
s16 temp3;
|
s16 temp3;
|
||||||
|
|
||||||
// @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted).
|
// @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted).
|
||||||
s8 stick_y = play->state.input[0].rel.stick_y;
|
// Also add in the analog camera Y input. Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
|
s32 stick_y = CLAMP(play->state.input[0].rel.stick_y + analog_y, -61, 61);
|
||||||
if (!inverted_y) {
|
if (!inverted_y) {
|
||||||
stick_y = -stick_y;
|
stick_y = -stick_y;
|
||||||
}
|
}
|
||||||
|
|
@ -95,8 +115,9 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
|
||||||
|
|
||||||
var_s0 = this->actor.focus.rot.y - this->actor.shape.rot.y;
|
var_s0 = this->actor.focus.rot.y - this->actor.shape.rot.y;
|
||||||
|
|
||||||
// @recomp Invert the X axis accordingly.
|
// @recomp Invert the X axis accordingly. Also add in the analog camera Y input.
|
||||||
s8 stick_x = play->state.input[0].rel.stick_x;
|
// Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
|
s32 stick_x = CLAMP(play->state.input[0].rel.stick_x + analog_x, -61, 61);
|
||||||
if (inverted_x) {
|
if (inverted_x) {
|
||||||
stick_x = -stick_x;
|
stick_x = -stick_x;
|
||||||
}
|
}
|
||||||
|
|
@ -113,6 +134,133 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
|
||||||
return func_80832754(this, (play->unk_1887C != 0) || func_800B7128(this) || func_8082EF20(this));
|
return func_80832754(this, (play->unk_1887C != 0) || func_800B7128(this) || func_8082EF20(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern Input* sPlayerControlInput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update for using telescopes. SCENE_AYASHIISHOP acts quite differently: it has a different camera mode and cannot use
|
||||||
|
* zooming.
|
||||||
|
*
|
||||||
|
* - Stick inputs move the view; shape.rot.y is used as a base position which cannot be looked too far away from. (This
|
||||||
|
* is not necessarily the same as the original angle of the spawn.)
|
||||||
|
* - A can be used to zoom (except in SCENE_AYASHIISHOP)
|
||||||
|
* - B exits, using the RESPAWN_MODE_DOWN entrance
|
||||||
|
*/
|
||||||
|
// @recomp Patched for aiming inversion and supporting the right stick in dual analog.
|
||||||
|
void func_8083A98C(Actor* thisx, PlayState* play2) {
|
||||||
|
PlayState* play = play2;
|
||||||
|
Player* this = (Player*)thisx;
|
||||||
|
s32 camMode;
|
||||||
|
|
||||||
|
if (play->csCtx.state != CS_STATE_IDLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @recomp Get the aiming camera inversion state.
|
||||||
|
s32 inverted_x, inverted_y;
|
||||||
|
recomp_get_inverted_axes(&inverted_x, &inverted_y);
|
||||||
|
// @recomp Get the analog camera input values if analog cam is enabled.
|
||||||
|
s32 analog_x = 0;
|
||||||
|
s32 analog_y = 0;
|
||||||
|
if (recomp_analog_cam_enabled()) {
|
||||||
|
float analog_x_float = 0.0f;
|
||||||
|
float analog_y_float = 0.0f;
|
||||||
|
recomp_get_camera_inputs(&analog_x_float, &analog_y_float);
|
||||||
|
// Scale by 127 to match what ultramodern does, then clamp to 60 to match the game's handling.
|
||||||
|
analog_x = (s32)(analog_x_float * 127.0f);
|
||||||
|
analog_x = CLAMP(analog_x, -60, 60);
|
||||||
|
analog_y = (s32)(analog_y_float * -127.0f);
|
||||||
|
analog_y = CLAMP(analog_y, -60, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DECR(this->av2.actionVar2) != 0) {
|
||||||
|
camMode = (play->sceneId != SCENE_AYASHIISHOP) ? CAM_MODE_FIRSTPERSON : CAM_MODE_DEKUHIDE;
|
||||||
|
|
||||||
|
// Show controls overlay. SCENE_AYASHIISHOP does not have Zoom, so has a different one.
|
||||||
|
if (this->av2.actionVar2 == 1) {
|
||||||
|
Message_StartTextbox(play, (play->sceneId == SCENE_AYASHIISHOP) ? 0x2A00 : 0x5E6, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// @recomp Manual relocation, TODO remove when automated.
|
||||||
|
Input* player_control_input = play->state.input;
|
||||||
|
*(Input**)KaleidoManager_GetRamAddr(&sPlayerControlInput) = player_control_input;
|
||||||
|
if (play->view.fovy >= 25.0f) {
|
||||||
|
s16 prevFocusX = thisx->focus.rot.x;
|
||||||
|
s16 prevFocusY = thisx->focus.rot.y;
|
||||||
|
s16 inputY;
|
||||||
|
s16 inputX;
|
||||||
|
s16 newYaw; // from base position shape.rot.y
|
||||||
|
|
||||||
|
// @recomp Add in the analog camera Y input. Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
|
// Pitch:
|
||||||
|
inputY = CLAMP(player_control_input->rel.stick_y + analog_y, -60, 60) * 4;
|
||||||
|
// @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted).
|
||||||
|
if (!inverted_y) {
|
||||||
|
inputY = -inputY;
|
||||||
|
}
|
||||||
|
// Add input, clamped to prevent turning too fast
|
||||||
|
thisx->focus.rot.x += CLAMP(inputY, -0x12C, 0x12C);
|
||||||
|
// Prevent looking too far up or down
|
||||||
|
thisx->focus.rot.x = CLAMP(thisx->focus.rot.x, -0x2EE0, 0x2EE0);
|
||||||
|
|
||||||
|
// @recomp Add in the analog camera X input. Clamp to prevent moving the camera twice as fast if both sticks are held.
|
||||||
|
// Yaw: shape.rot.y is used as a fixed starting position
|
||||||
|
inputX = CLAMP(player_control_input->rel.stick_x + analog_x, -60, 60) * -4;
|
||||||
|
// @recomp Invert the X axis accordingly.
|
||||||
|
if (inverted_x) {
|
||||||
|
inputX = -inputX;
|
||||||
|
}
|
||||||
|
// Start from current position: no input -> no change
|
||||||
|
newYaw = thisx->focus.rot.y - thisx->shape.rot.y;
|
||||||
|
// Add input, clamped to prevent turning too fast
|
||||||
|
newYaw += CLAMP(inputX, -0x12C, 0x12C);
|
||||||
|
// Prevent looking too far left or right of base position
|
||||||
|
newYaw = CLAMP(newYaw, -0x3E80, 0x3E80);
|
||||||
|
thisx->focus.rot.y = thisx->shape.rot.y + newYaw;
|
||||||
|
|
||||||
|
if (play->sceneId == SCENE_00KEIKOKU) {
|
||||||
|
f32 focusDeltaX = (s16)(thisx->focus.rot.x - prevFocusX);
|
||||||
|
f32 focusDeltaY = (s16)(thisx->focus.rot.y - prevFocusY);
|
||||||
|
|
||||||
|
Audio_PlaySfx_AtPosWithFreq(&gSfxDefaultPos, NA_SE_PL_TELESCOPE_MOVEMENT - SFX_FLAG,
|
||||||
|
sqrtf(SQ(focusDeltaX) + SQ(focusDeltaY)) / 300.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (play->sceneId == SCENE_AYASHIISHOP) {
|
||||||
|
camMode = CAM_MODE_DEKUHIDE;
|
||||||
|
} else if (CHECK_BTN_ALL(player_control_input->cur.button, BTN_A)) { // Zoom
|
||||||
|
camMode = CAM_MODE_TARGET;
|
||||||
|
} else {
|
||||||
|
camMode = CAM_MODE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit
|
||||||
|
if (CHECK_BTN_ALL(player_control_input->press.button, BTN_B)) {
|
||||||
|
Message_CloseTextbox(play);
|
||||||
|
|
||||||
|
if (play->sceneId == SCENE_00KEIKOKU) {
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].entrance = ENTRANCE(ASTRAL_OBSERVATORY, 2);
|
||||||
|
} else {
|
||||||
|
u16 entrance;
|
||||||
|
|
||||||
|
if (play->sceneId == SCENE_AYASHIISHOP) {
|
||||||
|
entrance = ENTRANCE(CURIOSITY_SHOP, 3);
|
||||||
|
} else {
|
||||||
|
entrance = ENTRANCE(PIRATES_FORTRESS_INTERIOR, 8);
|
||||||
|
}
|
||||||
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].entrance = entrance;
|
||||||
|
}
|
||||||
|
|
||||||
|
func_80169EFC(&play->state);
|
||||||
|
gSaveContext.respawnFlag = -2;
|
||||||
|
play->transitionType = TRANS_TYPE_CIRCLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera_ChangeSetting(Play_GetCamera(play, CAM_ID_MAIN), CAM_SET_TELESCOPE);
|
||||||
|
Camera_ChangeMode(Play_GetCamera(play, CAM_ID_MAIN), camMode);
|
||||||
|
}
|
||||||
|
|
||||||
u32 sPlayerItemButtons[] = {
|
u32 sPlayerItemButtons[] = {
|
||||||
BTN_B,
|
BTN_B,
|
||||||
BTN_CLEFT,
|
BTN_CLEFT,
|
||||||
|
|
@ -203,9 +351,6 @@ u8* get_button_item_equip_ptr(u32 form, u32 button) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern Input* sPlayerControlInput;
|
|
||||||
|
|
||||||
// Return currently-pressed button, in order of priority D-Pad, B, CLEFT, CDOWN, CRIGHT.
|
// Return currently-pressed button, in order of priority D-Pad, B, CLEFT, CDOWN, CRIGHT.
|
||||||
EquipSlot func_8082FDC4(void) {
|
EquipSlot func_8082FDC4(void) {
|
||||||
EquipSlot i;
|
EquipSlot i;
|
||||||
|
|
@ -308,7 +453,8 @@ void Player_Action_86(Player *this, PlayState *play) {
|
||||||
s32 sp48 = false;
|
s32 sp48 = false;
|
||||||
|
|
||||||
func_808323C0(this, play->playerCsIds[PLAYER_CS_ID_MASK_TRANSFORMATION]);
|
func_808323C0(this, play->playerCsIds[PLAYER_CS_ID_MASK_TRANSFORMATION]);
|
||||||
sPlayerControlInput = play->state.input;
|
// @recomp Manual relocation, TODO remove when automated.
|
||||||
|
*(Input**)KaleidoManager_GetRamAddr(&sPlayerControlInput) = play->state.input;
|
||||||
|
|
||||||
Camera_ChangeMode(GET_ACTIVE_CAM(play),
|
Camera_ChangeMode(GET_ACTIVE_CAM(play),
|
||||||
(this->transformation == PLAYER_FORM_HUMAN) ? CAM_MODE_NORMAL : CAM_MODE_JUMP);
|
(this->transformation == PLAYER_FORM_HUMAN) ? CAM_MODE_NORMAL : CAM_MODE_JUMP);
|
||||||
|
|
@ -337,7 +483,7 @@ void Player_Action_86(Player *this, PlayState *play) {
|
||||||
(sp48 =
|
(sp48 =
|
||||||
((this->transformation != PLAYER_FORM_HUMAN) || CHECK_WEEKEVENTREG(D_8085D908[GET_PLAYER_FORM])) &&
|
((this->transformation != PLAYER_FORM_HUMAN) || CHECK_WEEKEVENTREG(D_8085D908[GET_PLAYER_FORM])) &&
|
||||||
// @recomp Patched to also check for d-pad buttons for skipping the transformation cutscene.
|
// @recomp Patched to also check for d-pad buttons for skipping the transformation cutscene.
|
||||||
CHECK_BTN_ANY(sPlayerControlInput->press.button,
|
CHECK_BTN_ANY(play->state.input[0].press.button,
|
||||||
BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_B | BTN_A | BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)))) {
|
BTN_CRIGHT | BTN_CLEFT | BTN_CDOWN | BTN_CUP | BTN_B | BTN_A | BTN_DRIGHT | BTN_DLEFT | BTN_DDOWN | BTN_DUP)))) {
|
||||||
R_PLAY_FILL_SCREEN_ON = 45;
|
R_PLAY_FILL_SCREEN_ON = 45;
|
||||||
R_PLAY_FILL_SCREEN_R = 220;
|
R_PLAY_FILL_SCREEN_R = 220;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue