diff --git a/enhancements/reonucam3.patch b/enhancements/reonucam3.patch index 5305f7b..be289c3 100644 --- a/enhancements/reonucam3.patch +++ b/enhancements/reonucam3.patch @@ -16,7 +16,7 @@ index d266058..4b12426 100644 /** diff --git a/src/game/camera.c b/src/game/camera.c -index dfcf16a..ffdc1b2 100644 +index dfcf16a..82e4ed7 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -98,6 +98,7 @@ Vec3f sPlayer2FocusOffset; @@ -69,28 +69,45 @@ index dfcf16a..ffdc1b2 100644 if (camCeilHeight != CELL_HEIGHT_LIMIT) { camCeilHeight -= baseOff; if ((c->pos[1] > camCeilHeight && sMarioGeometry.currFloorHeight + baseOff < camCeilHeight) -@@ -934,9 +940,19 @@ s32 update_8_directions_camera(struct Camera *c, Vec3f focus, Vec3f pos) { +@@ -934,8 +940,36 @@ s32 update_8_directions_camera(struct Camera *c, Vec3f focus, Vec3f pos) { UNUSED f32 unused1; UNUSED f32 unused2; UNUSED f32 unused3; - f32 yOff = 125.f; + f32 yOff; f32 baseDist = 1000.f; - ++ Vec3f mPos; ++ + if (gMarioState->action & ACT_FLAG_SWIMMING) { + yOff = -125.f; + } else { + yOff = 125.f; + } + -+ if ((gPlayer1Controller->buttonDown & L_TRIG) && !(gMarioState->action & ACT_FLAG_SWIMMING_OR_FLYING)) { -+ pitch = DEGREES(65); ++ mPos[1] = gMarioState->pos[1]; ++ mPos[0] = gMarioState->pos[0] + (sins(gMarioState->faceAngle[1]) * 100.0f); ++ mPos[2] = gMarioState->pos[2] + (coss(gMarioState->faceAngle[1]) * 100.0f); ++ ++ if (gPlayer1Controller->buttonDown & U_JPAD) { ++ gCliffTimer = 60; + } + ++ if (gPlayer1Controller->buttonDown & U_JPAD ++ || (absf(mPos[1] - gMarioState->floorHeight) < 300.0f && mPos[1] - find_floor_height(mPos[0], mPos[1], mPos[2]) > 300.0f)) { ++ if (gCliffTimer > 59) ++ gCliffTimer = 59; ++ if (++gCliffTimer > 20) { ++ pitch = DEGREES(gCliffTimer - 10); ++ } ++ } else if (!(gPlayer1Controller->buttonDown & U_JPAD)) { ++ gCliffTimer -= 2; ++ if (gCliffTimer < 0) ++ gCliffTimer = 0; ++ } + sAreaYaw = camYaw; calc_y_to_curr_floor(&posY, 1.f, 200.f, &focusY, 0.9f, 200.f); - focus_on_mario(focus, pos, posY + yOff, focusY + yOff, sLakituDist + baseDist, pitch, camYaw); -@@ -1170,6 +1186,28 @@ void mode_radial_camera(struct Camera *c) { +@@ -1170,6 +1204,28 @@ void mode_radial_camera(struct Camera *c) { pan_ahead_of_player(c); } @@ -119,7 +136,7 @@ index dfcf16a..ffdc1b2 100644 /** * A mode that only has 8 camera angles, 45 degrees apart */ -@@ -1177,42 +1215,59 @@ void mode_8_directions_camera(struct Camera *c) { +@@ -1177,42 +1233,59 @@ void mode_8_directions_camera(struct Camera *c) { Vec3f pos; UNUSED u8 unused[8]; s16 oldAreaYaw = sAreaYaw; @@ -131,13 +148,7 @@ index dfcf16a..ffdc1b2 100644 - if (gPlayer1Controller->buttonPressed & R_CBUTTONS) { - s8DirModeYawOffset += DEGREES(45); - play_sound_cbutton_side(); -+ if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { -+ s8DirModeBaseYaw -= DEGREES(45); -+ } else if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { -+ s8DirModeBaseYaw += DEGREES(45); -+ } else if (gPlayer2Controller->rawStickX) { -+ s8DirModeBaseYaw += DEGREES(gPlayer2Controller->rawStickX * 4 / 64); // Analog camera support (Use the "Dual Analog" input mode in Parallel Launcher) - } +- } - if (gPlayer1Controller->buttonPressed & L_CBUTTONS) { - s8DirModeYawOffset -= DEGREES(45); - play_sound_cbutton_side(); @@ -147,7 +158,13 @@ index dfcf16a..ffdc1b2 100644 - else if (gPlayer1Controller->buttonPressed & U_JPAD) { - s8DirModeYawOffset = 0; - s8DirModeYawOffset = gMarioState->faceAngle[1]-0x8000; -- } ++ if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { ++ s8DirModeBaseYaw -= DEGREES(45); ++ } else if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { ++ s8DirModeBaseYaw += DEGREES(45); ++ } else if (gPlayer2Controller->rawStickX) { ++ s8DirModeBaseYaw += DEGREES(gPlayer2Controller->rawStickX * 4 / 64); // Analog camera support (Use the "Dual Analog" input mode in Parallel Launcher) + } - else if (gPlayer1Controller->buttonDown & L_JPAD) { - s8DirModeYawOffset -= DEGREES(2); + @@ -159,7 +176,7 @@ index dfcf16a..ffdc1b2 100644 + } + rButtonCounter++; // This increses whenever R is held. + } else { -+ if (rButtonCounter > 0 && rButtonCounter <= 5 && !((gPlayer1Controller->buttonDown & L_CBUTTONS) || (gPlayer1Controller->buttonDown & R_CBUTTONS))) { ++ if (rButtonCounter > 0 && rButtonCounter <= 5 && !((gPlayer1Controller->buttonDown & L_CBUTTONS) || (gPlayer1Controller->buttonDown & R_CBUTTONS) || (gMarioState->action & ACT_FLAG_SWIMMING_OR_FLYING))) { + // This centers the camera behind mario. It triggers when you let go of R in less than 5 frames. + s8DirModeYawOffset = 0; + s8DirModeBaseYaw = gMarioState->faceAngle[1]-0x8000; @@ -201,7 +218,16 @@ index dfcf16a..ffdc1b2 100644 /** * Updates the camera in outward radial mode. * sModeOffsetYaw is calculated in radial_camera_move, which calls offset_yaw_outward_radial -@@ -3036,20 +3091,21 @@ void update_lakitu(struct Camera *c) { +@@ -2116,7 +2189,7 @@ s16 update_default_camera(struct Camera *c) { + gLakituState.goalPos[1], + gLakituState.goalPos[2], &ceil); + s16 yawDir; +- ++ set_camera_mode_8_directions(c); + handle_c_button_movement(c); + vec3f_get_dist_and_angle(sMarioCamState->pos, c->pos, &dist, &pitch, &yaw); + +@@ -3036,20 +3109,21 @@ void update_lakitu(struct Camera *c) { void update_camera(struct Camera *c) { UNUSED u8 unused[24]; @@ -227,7 +253,7 @@ index dfcf16a..ffdc1b2 100644 } // Initialize the camera -@@ -4849,15 +4905,15 @@ void play_camera_buzz_if_c_sideways(void) { +@@ -4849,15 +4923,15 @@ void play_camera_buzz_if_c_sideways(void) { } void play_sound_cbutton_up(void) { @@ -246,7 +272,7 @@ index dfcf16a..ffdc1b2 100644 } void play_sound_button_change_blocked(void) { -@@ -4961,7 +5017,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { +@@ -4961,7 +5035,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom in / enter C-Up @@ -255,7 +281,7 @@ index dfcf16a..ffdc1b2 100644 if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags &= ~CAM_MOVE_ZOOMED_OUT; play_sound_cbutton_up(); -@@ -4971,7 +5027,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { +@@ -4971,7 +5045,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom out @@ -264,7 +290,7 @@ index dfcf16a..ffdc1b2 100644 if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags |= CAM_MOVE_ALREADY_ZOOMED_OUT; #ifndef VERSION_JP -@@ -4983,6 +5039,12 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { +@@ -4983,6 +5057,12 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } } @@ -277,7 +303,7 @@ index dfcf16a..ffdc1b2 100644 //! returning uninitialized variable return dummy; } -@@ -5548,7 +5610,7 @@ void set_camera_mode_8_directions(struct Camera *c) { +@@ -5548,7 +5628,7 @@ void set_camera_mode_8_directions(struct Camera *c) { if (c->mode != CAMERA_MODE_8_DIRECTIONS) { c->mode = CAMERA_MODE_8_DIRECTIONS; sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT; @@ -287,20 +313,21 @@ index dfcf16a..ffdc1b2 100644 } } diff --git a/src/game/game_init.c b/src/game/game_init.c -index 6cfa8f5..238378c 100644 +index 6cfa8f5..16f6bf2 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c -@@ -46,6 +46,9 @@ OSContPad gControllerPads[4]; +@@ -46,6 +46,10 @@ OSContPad gControllerPads[4]; u8 gControllerBits; u8 gIsConsole; u8 gBorderHeight; +u8 gCameraSpeed = 2; +u8 gWaterCamOverride; +u8 gFlyingCamOverride; ++s32 gCliffTimer; #ifdef EEP s8 gEepromProbe; #endif -@@ -715,6 +718,7 @@ void thread5_game_loop(UNUSED void *arg) { +@@ -715,6 +719,7 @@ void thread5_game_loop(UNUSED void *arg) { play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); set_sound_mode(save_file_get_sound_mode()); @@ -309,16 +336,17 @@ index 6cfa8f5..238378c 100644 gWidescreen = save_file_get_widescreen_mode(); #endif diff --git a/src/game/game_init.h b/src/game/game_init.h -index 87386ce..1d69560 100644 +index 87386ce..9cec2f5 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h -@@ -45,6 +45,9 @@ extern u8 gIsConsole; +@@ -45,6 +45,10 @@ extern u8 gIsConsole; #ifdef WIDE extern u8 gWidescreen; #endif +extern u8 gCameraSpeed; +extern u8 gWaterCamOverride; +extern u8 gFlyingCamOverride; ++extern s32 gCliffTimer; extern u8 gBorderHeight; #ifdef EEP extern s8 gEepromProbe; @@ -394,7 +422,7 @@ index 9cd458a..ac2d18c 100644 gWidescreen ^= 1; save_file_set_widescreen_mode(gWidescreen); diff --git a/src/game/mario.c b/src/game/mario.c -index b381afa..d935245 100644 +index b381afa..7cb9549 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1443,32 +1443,39 @@ void update_mario_inputs(struct MarioState *m) { @@ -452,21 +480,21 @@ index b381afa..d935245 100644 + } else { + set_camera_mode(m->area->camera, CAMERA_MODE_8_DIRECTIONS, 1); + } -+ if (gPlayer1Controller->buttonPressed & L_TRIG) { ++ if ((gPlayer1Controller->buttonPressed & R_TRIG) && (m->action & ACT_FLAG_SWIMMING)) { + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; + gWaterCamOverride ^= 1; } } diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c -index ce6467e..9ebb861 100644 +index ce6467e..c7e998c 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -1736,6 +1736,10 @@ s32 act_shot_from_cannon(struct MarioState *m) { s32 act_flying(struct MarioState *m) { s16 startPitch = m->faceAngle[0]; -+ if (gPlayer1Controller->buttonPressed & L_TRIG) { ++ if (gPlayer1Controller->buttonPressed & R_TRIG) { + gFlyingCamOverride ^= 1; + } + @@ -532,14 +560,14 @@ index b27d869..7fbf045 100644 if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) { switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) { diff --git a/src/game/save_file.h b/src/game/save_file.h -index 00fc042..dd394a6 100644 +index 00fc042..7062ead 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -62,6 +62,7 @@ struct MainMenuSaveData #ifdef WIDE u8 wideMode: 1; #endif -+ u8 cameraSpeedSetting; ++ u8 cameraSpeedSetting: 3; #ifdef VERSION_EU u16 language; diff --git a/include/text_strings.h.in b/include/text_strings.h.in index d266058..4b12426 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -34,6 +34,12 @@ #define TEXT_HUD_WIDE_INFO2 _("STRETCH THE IMAGE TO 16:9") #endif +#define TEXT_CAM_INFO_SLOWEST _("CAM SPEED: SLOWEST") +#define TEXT_CAM_INFO_SLOW _("CAM SPEED: SLOW") +#define TEXT_CAM_INFO_MEDIUM _("CAM SPEED: MEDIUM") +#define TEXT_CAM_INFO_FAST _("CAM SPEED: FAST") +#define TEXT_CAM_INFO_FASTEST _("CAM SPEED: FASTEST") + #if defined(VERSION_JP) || defined(VERSION_SH) /** diff --git a/src/game/camera.c b/src/game/camera.c index dfcf16a..954f537 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -98,6 +98,7 @@ Vec3f sPlayer2FocusOffset; * The pitch used for the credits easter egg. */ s16 sCreditsPlayer2Pitch; +s16 rButtonCounter2; /** * The yaw used for the credits easter egg. */ @@ -107,6 +108,7 @@ s16 sCreditsPlayer2Yaw; */ u8 sFramesPaused; + extern struct CameraFOVStatus sFOVState; extern struct TransitionInfo sModeTransition; extern struct PlayerGeometry sMarioGeometry; @@ -259,6 +261,7 @@ s16 sCameraSoundFlags; * Stores what C-Buttons are pressed this frame. */ u16 sCButtonsPressed; +u16 rButtonCounter; /** * A copy of gDialogID, the dialog displayed during the cutscene. */ @@ -437,6 +440,7 @@ u8 sFramesSinceCutsceneEnded = 0; * 3 = Dialog doesn't have a response */ u8 sCutsceneDialogResponse = DIALOG_RESPONSE_NONE; +u8 stickReset = 1; struct PlayerCameraState *sMarioCamState = &gPlayerCameraState[0]; struct PlayerCameraState *sLuigiCamState = &gPlayerCameraState[1]; u32 unused8032D008 = 0; @@ -755,6 +759,7 @@ void set_camera_height(struct Camera *c, f32 goalHeight) { UNUSED s16 action = sMarioCamState->action; f32 baseOff = 125.f; f32 camCeilHeight = find_ceil(c->pos[0], gLakituState.goalPos[1] - 50.f, c->pos[2], &surface); + f32 approachRate = 20.0f; if (sMarioCamState->action & ACT_FLAG_HANGING) { marioCeilHeight = sMarioGeometry.currCeilHeight; @@ -790,7 +795,8 @@ void set_camera_height(struct Camera *c, f32 goalHeight) { c->pos[1] = goalHeight; } } - approach_camera_height(c, goalHeight, 20.f); + approachRate += ABS(c->pos[1] - goalHeight) / 20; + approach_camera_height(c, goalHeight, approachRate); if (camCeilHeight != CELL_HEIGHT_LIMIT) { camCeilHeight -= baseOff; if ((c->pos[1] > camCeilHeight && sMarioGeometry.currFloorHeight + baseOff < camCeilHeight) @@ -934,9 +940,18 @@ s32 update_8_directions_camera(struct Camera *c, Vec3f focus, Vec3f pos) { UNUSED f32 unused1; UNUSED f32 unused2; UNUSED f32 unused3; - f32 yOff = 125.f; + f32 yOff; f32 baseDist = 1000.f; + if (gMarioState->action & ACT_FLAG_SWIMMING) { + yOff = -125.f; + } else { + yOff = 125.f; + } + + if ((gPlayer1Controller->buttonDown & R_TRIG) && (gPlayer1Controller->buttonDown & U_CBUTTONS)) + pitch = DEGREES(60); + sAreaYaw = camYaw; calc_y_to_curr_floor(&posY, 1.f, 200.f, &focusY, 0.9f, 200.f); focus_on_mario(focus, pos, posY + yOff, focusY + yOff, sLakituDist + baseDist, pitch, camYaw); @@ -1170,6 +1185,28 @@ void mode_radial_camera(struct Camera *c) { pan_ahead_of_player(c); } +// Returns the camera speed based on the user's camera speed setting +f32 set_camera_speed(void) { + switch(gCameraSpeed) { + case 0: + return 0.5f; + break; + case 1: + return 1; + break; + case 2: + return 1.5; + break; + case 3: + return 2; + break; + case 4: + return 3.5; + break; + } + return 0; +} + /** * A mode that only has 8 camera angles, 45 degrees apart */ @@ -1177,42 +1214,59 @@ void mode_8_directions_camera(struct Camera *c) { Vec3f pos; UNUSED u8 unused[8]; s16 oldAreaYaw = sAreaYaw; + // Get the camera speed based on the user's setting + f32 cameraSpeed = set_camera_speed(); radial_camera_input(c, 0.f); - if (gPlayer1Controller->buttonPressed & R_CBUTTONS) { - s8DirModeYawOffset += DEGREES(45); - play_sound_cbutton_side(); + if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { + s8DirModeBaseYaw -= DEGREES(45); + } else if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { + s8DirModeBaseYaw += DEGREES(45); + } else if (gPlayer2Controller->rawStickX) { + s8DirModeBaseYaw += DEGREES(gPlayer2Controller->rawStickX * 4 / 64); // Analog camera support (Use the "Dual Analog" input mode in Parallel Launcher) } - if (gPlayer1Controller->buttonPressed & L_CBUTTONS) { - s8DirModeYawOffset -= DEGREES(45); - play_sound_cbutton_side(); - } -#ifdef PARALLEL_LAKITU_CAM - // extra functionality - else if (gPlayer1Controller->buttonPressed & U_JPAD) { - s8DirModeYawOffset = 0; - s8DirModeYawOffset = gMarioState->faceAngle[1]-0x8000; - } - else if (gPlayer1Controller->buttonDown & L_JPAD) { - s8DirModeYawOffset -= DEGREES(2); + + if (gPlayer1Controller->buttonDown & R_TRIG) { + if (gPlayer1Controller->buttonDown & L_CBUTTONS) { + s8DirModeBaseYaw -= DEGREES(cameraSpeed); + } else if (gPlayer1Controller->buttonDown & R_CBUTTONS) { + s8DirModeBaseYaw += DEGREES(cameraSpeed); + } + rButtonCounter++; // This increses whenever R is held. + } else { + if (rButtonCounter > 0 && rButtonCounter <= 5 && !((gPlayer1Controller->buttonDown & L_CBUTTONS) || (gPlayer1Controller->buttonDown & R_CBUTTONS) || (gMarioState->action & ACT_FLAG_SWIMMING_OR_FLYING))) { + // This centers the camera behind mario. It triggers when you let go of R in less than 5 frames. + s8DirModeYawOffset = 0; + s8DirModeBaseYaw = gMarioState->faceAngle[1]-0x8000; + gMarioState->area->camera->yaw = s8DirModeBaseYaw; + play_sound_rbutton_changed(); + } + rButtonCounter = 0; + } + if (gPlayer1Controller->buttonPressed & R_TRIG) { + if (rButtonCounter2 <= 5) { + set_cam_angle(CAM_ANGLE_MARIO); // Enter mario cam if R is pressed 2 times in less than 5 frames + rButtonCounter2 = 6; + } else { + rButtonCounter2 = 0; + } + } else { + rButtonCounter2++; } - else if (gPlayer1Controller->buttonDown & R_JPAD) { - s8DirModeYawOffset += DEGREES(2); + if (gPlayer1Controller->buttonPressed & D_JPAD) { + s8DirModeBaseYaw = (s8DirModeBaseYaw + 0x1000) & 0xE000; // Lock the camera to the nearest 45deg axis } - else if (gPlayer1Controller->buttonPressed & D_JPAD) { - s8DirModeYawOffset = s8DirModeYawOffset&0xE000; - } -#endif lakitu_zoom(400.f, 0x900); c->nextYaw = update_8_directions_camera(c, c->focus, pos); + set_camera_height(c, pos[1]); c->pos[0] = pos[0]; c->pos[2] = pos[2]; sAreaYawChange = sAreaYaw - oldAreaYaw; - set_camera_height(c, pos[1]); } + /** * Updates the camera in outward radial mode. * sModeOffsetYaw is calculated in radial_camera_move, which calls offset_yaw_outward_radial @@ -2116,7 +2170,7 @@ s16 update_default_camera(struct Camera *c) { gLakituState.goalPos[1], gLakituState.goalPos[2], &ceil); s16 yawDir; - + set_camera_mode_8_directions(c); handle_c_button_movement(c); vec3f_get_dist_and_angle(sMarioCamState->pos, c->pos, &dist, &pitch, &yaw); @@ -3036,20 +3090,21 @@ void update_lakitu(struct Camera *c) { void update_camera(struct Camera *c) { UNUSED u8 unused[24]; + extern s16 s8DirModeBaseYaw; + gCamera = c; update_camera_hud_status(c); if (c->cutscene == 0) { // Only process R_TRIG if 'fixed' is not selected in the menu if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) { if (gPlayer1Controller->buttonPressed & R_TRIG) { - if (set_cam_angle(0) == CAM_ANGLE_LAKITU) { - set_cam_angle(CAM_ANGLE_MARIO); - } else { + if (set_cam_angle(0) == CAM_ANGLE_MARIO) { + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; set_cam_angle(CAM_ANGLE_LAKITU); } } } - play_sound_if_cam_switched_to_lakitu_or_mario(); + //play_sound_if_cam_switched_to_lakitu_or_mario(); } // Initialize the camera @@ -4849,15 +4904,15 @@ void play_camera_buzz_if_c_sideways(void) { } void play_sound_cbutton_up(void) { - play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); } void play_sound_cbutton_down(void) { - play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); } void play_sound_cbutton_side(void) { - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); } void play_sound_button_change_blocked(void) { @@ -4961,7 +5016,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom in / enter C-Up - if (gPlayer1Controller->buttonPressed & U_CBUTTONS) { + if (((gPlayer1Controller->buttonPressed & U_CBUTTONS) || (gPlayer2Controller->rawStickY > 40)) && (stickReset) && !(gPlayer1Controller->buttonDown & R_TRIG)) { if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags &= ~CAM_MOVE_ZOOMED_OUT; play_sound_cbutton_up(); @@ -4971,7 +5026,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom out - if (gPlayer1Controller->buttonPressed & D_CBUTTONS) { + if ((gPlayer1Controller->buttonPressed & D_CBUTTONS) || (gPlayer2Controller->rawStickY < -40)) { if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags |= CAM_MOVE_ALREADY_ZOOMED_OUT; #ifndef VERSION_JP @@ -4983,6 +5038,12 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } } + if ((gPlayer2Controller->rawStickY > 40) || (gPlayer2Controller->rawStickY < -40)) { + stickReset = 0; + } else { + stickReset = 1; + } + //! returning uninitialized variable return dummy; } @@ -5548,7 +5609,7 @@ void set_camera_mode_8_directions(struct Camera *c) { if (c->mode != CAMERA_MODE_8_DIRECTIONS) { c->mode = CAMERA_MODE_8_DIRECTIONS; sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT; - s8DirModeBaseYaw = 0; + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; s8DirModeYawOffset = 0; } } diff --git a/src/game/game_init.c b/src/game/game_init.c index 6cfa8f5..16f6bf2 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -46,6 +46,10 @@ OSContPad gControllerPads[4]; u8 gControllerBits; u8 gIsConsole; u8 gBorderHeight; +u8 gCameraSpeed = 2; +u8 gWaterCamOverride; +u8 gFlyingCamOverride; +s32 gCliffTimer; #ifdef EEP s8 gEepromProbe; #endif @@ -715,6 +719,7 @@ void thread5_game_loop(UNUSED void *arg) { play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); set_sound_mode(save_file_get_sound_mode()); + gCameraSpeed = (save_file_get_camera_speed()); #ifdef WIDE gWidescreen = save_file_get_widescreen_mode(); #endif diff --git a/src/game/game_init.h b/src/game/game_init.h index 87386ce..9cec2f5 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -45,6 +45,10 @@ extern u8 gIsConsole; #ifdef WIDE extern u8 gWidescreen; #endif +extern u8 gCameraSpeed; +extern u8 gWaterCamOverride; +extern u8 gFlyingCamOverride; +extern s32 gCliffTimer; extern u8 gBorderHeight; #ifdef EEP extern s8 gEepromProbe; diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 9cd458a..ac2d18c 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -39,6 +39,12 @@ u8 textWideInfo[] = { TEXT_HUD_WIDE_INFO }; u8 textWideInfo2[] = { TEXT_HUD_WIDE_INFO2 }; #endif +u8 textCamInfoSlowest[] = { TEXT_CAM_INFO_SLOWEST }; +u8 textCamInfoSlow[] = { TEXT_CAM_INFO_SLOW }; +u8 textCamInfoMedium[] = { TEXT_CAM_INFO_MEDIUM }; +u8 textCamInfoFast[] = { TEXT_CAM_INFO_FAST}; +u8 textCamInfoFastest[] = { TEXT_CAM_INFO_FASTEST }; + extern u8 gLastCompletedCourseNum; extern u8 gLastCompletedStarNum; @@ -1350,6 +1356,45 @@ void reset_red_coins_collected(void) { gRedCoinsCollected = 0; } +void render_camera_speed_setting(void) { + gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); + switch (gCameraSpeed) { + case 0: + print_generic_string(190, 20, textCamInfoSlowest); + break; + case 1: + print_generic_string(190, 20, textCamInfoSlow); + break; + case 2: + print_generic_string(190, 20, textCamInfoMedium); + break; + case 3: + print_generic_string(190, 20, textCamInfoFast); + break; + case 4: + print_generic_string(190, 20, textCamInfoFastest); + break; + } + gSPDisplayList(gDisplayListHead++, dl_ia_text_end); + + if (gPlayer1Controller->buttonPressed & R_JPAD) { + if (gCameraSpeed < 4) { + gCameraSpeed += 1; + } else { + gCameraSpeed = 0; + } + save_file_set_camera_speed(gCameraSpeed); + } else if (gPlayer1Controller->buttonPressed & L_JPAD) { + if (gCameraSpeed > 0) { + gCameraSpeed -= 1; + } else { + gCameraSpeed = 4; + } + save_file_set_camera_speed(gCameraSpeed); + } +} + void change_dialog_camera_angle(void) { if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) { gDialogCameraAngleIndex = CAM_SELECTION_MARIO; @@ -1779,6 +1824,7 @@ s16 render_pause_courses_and_castle(void) { } #ifdef WIDE render_widescreen_setting(); + render_camera_speed_setting(); if (gPlayer1Controller->buttonPressed & L_TRIG){ gWidescreen ^= 1; save_file_set_widescreen_mode(gWidescreen); diff --git a/src/game/mario.c b/src/game/mario.c index b381afa..7cb9549 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1443,32 +1443,39 @@ void update_mario_inputs(struct MarioState *m) { void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { f32 heightBelowWater; s16 camPreset; + extern s16 s8DirModeBaseYaw; + if (!gWaterCamOverride) { + if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) { + heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; + camPreset = m->area->camera->mode; + if (m->action & ACT_FLAG_METAL_WATER) { + if (camPreset != CAMERA_MODE_CLOSE) { + set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); + } + } else { + if ((heightBelowWater > 800.0f) && (camPreset != CAMERA_MODE_BEHIND_MARIO)) { + set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); + } - if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) { - heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; - camPreset = m->area->camera->mode; - - if (m->action & ACT_FLAG_METAL_WATER) { - if (camPreset != CAMERA_MODE_CLOSE) { - set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); - } - } else { - if ((heightBelowWater > 800.0f) && (camPreset != CAMERA_MODE_BEHIND_MARIO)) { - set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); - } - - if ((heightBelowWater < 400.0f) && (camPreset != CAMERA_MODE_WATER_SURFACE)) { - set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); - } + if ((heightBelowWater < 400.0f) && (camPreset != CAMERA_MODE_WATER_SURFACE)) { + set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); + } - // As long as Mario isn't drowning or at the top - // of the water with his head out, spawn bubbles. - if (!(m->action & ACT_FLAG_INTANGIBLE)) { - if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { - m->particleFlags |= PARTICLE_BUBBLE; + // As long as Mario isn't drowning or at the top + // of the water with his head out, spawn bubbles. + if (!(m->action & ACT_FLAG_INTANGIBLE)) { + if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { + m->particleFlags |= PARTICLE_BUBBLE; + } } } } + } else { + set_camera_mode(m->area->camera, CAMERA_MODE_8_DIRECTIONS, 1); + } + if ((gPlayer1Controller->buttonPressed & R_TRIG) && (m->action & ACT_FLAG_SWIMMING)) { + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; + gWaterCamOverride ^= 1; } } diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index ce6467e..c7e998c 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -1736,6 +1736,10 @@ s32 act_shot_from_cannon(struct MarioState *m) { s32 act_flying(struct MarioState *m) { s16 startPitch = m->faceAngle[0]; + if (gPlayer1Controller->buttonPressed & R_TRIG) { + gFlyingCamOverride ^= 1; + } + if (m->input & INPUT_Z_PRESSED) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); @@ -1750,8 +1754,10 @@ s32 act_flying(struct MarioState *m) { return set_mario_action(m, ACT_FREEFALL, 0); } - if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if (!gFlyingCamOverride) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); + } else { + set_camera_mode(m->area->camera, CAMERA_MODE_8_DIRECTIONS, 1); } if (m->actionState == 0) { @@ -1933,7 +1939,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { } if (m->vel[1] < 4.0f) { - if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if ((m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) && (!gFlyingCamOverride)) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); } @@ -1944,7 +1950,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { set_mario_action(m, ACT_FLYING, 1); } - if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO && (!gFlyingCamOverride)) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); } diff --git a/src/game/save_file.c b/src/game/save_file.c index b27d869..7fbf045 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -634,6 +634,12 @@ u8 save_file_get_widescreen_mode(void) { return gSaveBuffer.menuData[0].wideMode; } +void save_file_set_camera_speed(u8 speed) { + gSaveBuffer.menuData[0].cameraSpeedSetting = speed; + gMainMenuDataModified = TRUE; + save_main_menu_data(); +} + void save_file_set_widescreen_mode(u8 mode) { gSaveBuffer.menuData[0].wideMode = mode; @@ -646,6 +652,10 @@ u16 save_file_get_sound_mode(void) { return gSaveBuffer.menuData[0].soundMode; } +u8 save_file_get_camera_speed(void) { + return gSaveBuffer.menuData[0].cameraSpeedSetting; +} + void save_file_move_cap_to_default_location(void) { if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) { switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) { diff --git a/src/game/save_file.h b/src/game/save_file.h index 00fc042..7062ead 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -62,6 +62,7 @@ struct MainMenuSaveData #ifdef WIDE u8 wideMode: 1; #endif + u8 cameraSpeedSetting: 3; #ifdef VERSION_EU u16 language; @@ -167,6 +168,8 @@ u16 save_file_get_sound_mode(void); u8 save_file_get_widescreen_mode(void); void save_file_set_widescreen_mode(u8 mode); #endif +u8 save_file_get_camera_speed(void); +void save_file_set_camera_speed(u8 speed); void save_file_move_cap_to_default_location(void); void disable_warp_checkpoint(void);