From 966d7fc2908f5e1bee4f45fd456a4455434673e7 Mon Sep 17 00:00:00 2001 From: PeachyPeach <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Thu, 8 May 2025 00:52:06 +0200 Subject: [PATCH] Bettercam refactor and cleanup (#788) - `bettercamera` code refactoring, less spaghetti, more consistency - removed unused parts and added comments to the most obscure ones --- src/game/bettercamera.h | 85 ++- src/game/bettercamera.inc.h | 1088 +++++++++++---------------- src/game/camera.c | 14 +- src/game/hud.c | 18 +- src/game/mario.c | 2 +- src/game/mario_actions_airborne.c | 18 +- src/pc/controller/controller_sdl1.c | 7 +- src/pc/controller/controller_sdl2.c | 7 +- 8 files changed, 498 insertions(+), 741 deletions(-) diff --git a/src/game/bettercamera.h b/src/game/bettercamera.h index 206c86b0f..cd9e55943 100644 --- a/src/game/bettercamera.h +++ b/src/game/bettercamera.h @@ -1,44 +1,51 @@ -enum newcam_flagvalues -{ - NC_FLAG_XTURN = 0x0001,//If this flag is set, the camera's yaw can be moved by the player. - NC_FLAG_YTURN = 0x0002, //If this flag is set, the camera's pitch can be moved by the player. - NC_FLAG_ZOOM = 0x0004, //If this flag is set, the camera's distance can be set by the player. - NC_FLAG_8D = 0x0008, //If this flag is set, the camera will snap to an 8 directional axis - NC_FLAG_4D = 0x0010, //If this flag is set, the camera will snap to a 4 directional axis - NC_FLAG_2D = 0x0020, //If this flag is set, the camera will stick to 2D. - NC_FLAG_FOCUSX = 0x0040, //If this flag is set, the camera will point towards its focus on the X axis. - NC_FLAG_FOCUSY = 0x0080, //If this flag is set, the camera will point towards its focus on the Y axis. - NC_FLAG_FOCUSZ = 0x0100, //If this flag is set, the camera will point towards its focus on the Z axis. - NC_FLAG_POSX = 0x0200, //If this flag is set, the camera will move along the X axis. - NC_FLAG_POSY = 0x0400, //If this flag is set, the camera will move along the Y axis. - NC_FLAG_POSZ = 0x0800, //If this flag is set, the camera will move along the Z axis. - NC_FLAG_COLLISION = 0x1000, //If this flag is set, the camera will collide and correct itself with terrain. - NC_FLAG_SLIDECORRECT = 0x2000, //If this flag is set, the camera will attempt to centre itself behind Mario whenever he's sliding. +#ifndef BETTERCAMERA_H +#define BETTERCAMERA_H - NC_MODE_NORMAL = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, - NC_MODE_SLIDE = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION | NC_FLAG_SLIDECORRECT, - NC_MODE_FIXED = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ, - NC_MODE_2D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, - NC_MODE_8D = NC_FLAG_XTURN | NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_8D | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, - NC_MODE_FIXED_NOMOVE = 0x0000, - NC_MODE_NOTURN = NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION, - NC_MODE_NOROTATE = NC_FLAG_YTURN | NC_FLAG_ZOOM | NC_FLAG_FOCUSX | NC_FLAG_FOCUSY | NC_FLAG_FOCUSZ | NC_FLAG_POSX | NC_FLAG_POSY | NC_FLAG_POSZ | NC_FLAG_COLLISION +#include "types.h" -}; +typedef struct { -extern void newcam_init_settings(void); -extern void newcam_init_settings_override(bool override); -extern void newcam_diagnostics(void); + // Status + bool isActive; // basically the thing that governs if newcam is on. + bool isSlide; + Vec3f pos; // Position the camera is in the world + Vec3f posTarget; // The position the camera is basing calculations off. *Usually* Mario. + Vec3f lookAt; // Position the camera is looking at + f32 distance; // The distance the camera stays from the player + s32 distanceTargetIndex; + s16 yaw; // Z axis rotation + s16 yawTarget; // The yaw value the camera tries to set itself to when the centre flag is active. Is set to Mario's face angle. + f32 yawAccel; + s16 tilt; // Y axis rotation + f32 tiltAccel; + f32 panX; + f32 panZ; + s32 framesSinceCButtons[2]; + bool centering; // The flag that depicts wether the camera's going to try centering. + bool directionLocked; + s32 turnWait; // The amount of time to wait after landing before allowing the camera to turn again + s16 extStick[2]; + u8 savedMode; + u8 savedDefMode; -extern s16 newcam_sensitivityX; //How quick the camera works. -extern s16 newcam_sensitivityY; -extern s16 newcam_invertX; -extern s16 newcam_invertY; -extern s16 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking. -extern s16 newcam_aggression; //How much the camera tries to centre itself to Mario's facing and movement. -extern u8 newcam_active; // basically the thing that governs if newcam is on. -extern s16 newcam_analogue; -extern u16 newcam_intendedmode; + // Settings + s16 sensitivityX; // How quick the camera works. + s16 sensitivityY; + s16 panLevel; // How much the camera sticks out a bit in the direction you're looking. + s16 aggression; // How much the camera tries to centre itself to Mario's facing and movement. + f32 deceleration; + bool invertX; // Reverses movement of the camera axis. + bool invertY; + bool isMouse; + bool isAnalogue; // Weither to accept inputs from a player 2 joystick, and then disables C button input. + bool useDPad; + bool hasCollision; + bool LCentering; -extern u16 newcam_mode; -extern s16 newcam_yaw; \ No newline at end of file +} NewCamera; + +extern NewCamera gNewCamera; + +void newcam_init_settings(void); + +#endif // BETTERCAMERA_H diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index e04fb35d5..995b81686 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -11,659 +11,472 @@ #include "pc/controller/controller_mouse.h" #include "pc/lua/utils/smlua_camera_utils.h" -#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) +#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) //quick and dirty fix for some older MinGW.org mingwrt #else #include #endif -#define NEW_CAM_BOUNDING_BOX_RAYS 4 -#define NEW_CAM_BOUNDING_BOX_HRADIUS 250 -#define NEW_CAM_BOUNDING_BOX_VRADIUS 100 +#define NEWCAM_ACCEL 10 +#define NEWCAM_ACCEL_MAX 100 +#define NEWCAM_MARIO_HEIGHT 125 +#define NEWCAM_SAVED_MODE_NONE 0xFF +#define NEWCAM_DISTANCE_INC 250 +#define NEWCAM_YAW_STEP 0x3000 +#define NEWCAM_TILT_CENTERING 3000 +#define NEWCAM_TILT_LIMIT 0x3000 +#define NEWCAM_COLLISION_CHECK_WIDTH 75 +#define NEWCAM_COLLISION_CHECK_HEIGHT 90 -/** -Quick explanation of the camera modes - -NC_MODE_NORMAL: Standard mode, allows dualaxial movement and free control of the camera. -NC_MODE_FIXED: Disables control of camera, and the actual position of the camera doesn't update. -NC_MODE_2D: Disables horizontal control of the camera and locks Mario's direction to the X axis. NYI though. -NC_MODE_8D: 8 directional movement. Similar to standard, except the camera direction snaps to 8 directions. -NC_MODE_FIXED_NOMOVE: Disables control and movement of the camera. -NC_MODE_NOTURN: Disables horizontal and vertical control of the camera. - -Coop only uses NC_MODE_NORMAL and NC_MODE_SLIDE -**/ - -//!A bunch of developer intended options, to cover every base, really. -//#define NEWCAM_DEBUG //Some print values for puppycam. Not useful anymore, but never hurts to keep em around. -//#define nosound //If for some reason you hate the concept of audio, you can disable it. -//#define noaccel //Disables smooth movement of the camera with the C buttons. - -//!Hardcoded camera angle stuff. They're essentially area boxes that when Mario is inside, will trigger some view changes. -///Don't touch this btw, unless you know what you're doing, this has to be above for religious reasons. -UNUSED struct newcam_hardpos { - u8 newcam_hard_levelID; - u8 newcam_hard_areaID; - u8 newcam_hard_permaswap; - u16 newcam_hard_modeset; - s16 newcam_hard_X1; - s16 newcam_hard_Y1; - s16 newcam_hard_Z1; - s16 newcam_hard_X2; - s16 newcam_hard_Y2; - s16 newcam_hard_Z2; - s16 newcam_hard_camX; - s16 newcam_hard_camY; - s16 newcam_hard_camZ; - s16 newcam_hard_lookX; - s16 newcam_hard_lookY; - s16 newcam_hard_lookZ; +static const f32 NEWCAM_DISTANCES[] = { + 750, 1250, 2000 }; -///This is the bit that defines where the angles happen. They're basically environment boxes that dictate camera behaviour. -//Permaswap is a boolean that simply determines wether or not when the camera changes at this point it stays changed. 0 means it resets when you leave, and 1 means it stays changed. -//The camera position fields accept "32767" as an ignore flag. -UNUSED struct newcam_hardpos newcam_fixedcam[] = { - { - /*Level ID*/ 16,/*Area ID*/ 1,/*Permaswap*/ 0,/*Mode*/ NC_MODE_FIXED_NOMOVE, //Standard params. - /*X begin*/ -540,/*Y begin*/ 800,/*Z begin*/ -3500, //Where the activation box begins - /*X end*/ 540,/*Y end*/ 2000,/*Z end*/ -1500, //Where the activation box ends. - /*Cam X*/ 0,/*Cam Y*/ 1500,/*Cam Z*/ -1000, //The position the camera gets placed for NC_MODE_FIXED and NC_MODE_FIXED_NOMOVE - /*Look X*/ 0,/*Look Y*/ 800,/*Look Z*/ -2500 //The position the camera looks at for NC_MODE_FIXED_NOMOVE - }, +static const u32 NEWCAM_NUM_DISTANCES = sizeof(NEWCAM_DISTANCES) / sizeof(*NEWCAM_DISTANCES); + +NewCamera gNewCamera = { + + // Status + .isActive = false, + .isSlide = false, + .pos = { 0, 0, 0 }, + .posTarget = { 0, 0, 0 }, + .lookAt = { 0, 0, 0 }, + .distance = 750, // NEWCAM_DISTANCES[0] + .distanceTargetIndex = 0, + .yaw = 0, + .yawTarget = 0, + .yawAccel = 0, + .tilt = 1500, + .tiltAccel = 0, + .panX = 0, + .panZ = 0, + .framesSinceCButtons = { 0, 0 }, + .centering = false, + .directionLocked = false, + .turnWait = 0, + .extStick = { 0, 0 }, + .savedMode = NEWCAM_SAVED_MODE_NONE, + .savedDefMode = NEWCAM_SAVED_MODE_NONE, + + // Settings + .sensitivityX = 0, + .sensitivityY = 0, + .panLevel = 0, + .aggression = 0, + .deceleration = 1, + .invertX = false, + .invertY = false, + .isMouse = false, + .isAnalogue = false, + .useDPad = false, + .hasCollision = true, + .LCentering = true, }; - -#ifdef noaccel -u8 accel = 255; -#else -u8 accel = 10; -#endif // noaccel - -s16 newcam_yaw; //Z axis rotation -f32 newcam_yaw_accel; -s16 newcam_tilt = 1500; //Y axis rotation -f32 newcam_tilt_accel; -u16 newcam_distance = 750; //The distance the camera stays from the player -u16 newcam_distance_target = 750; //The distance the player camera tries to reach. -f32 newcam_pos_target[3]; //The position the camera is basing calculations off. *usually* Mario. -f32 newcam_pos[3]; //Position the camera is in the world -f32 newcam_lookat[3]; //Position the camera is looking at -f32 newcam_framessincec[2]; -f32 newcam_extheight = 125; -u8 newcam_centering = 0; // The flag that depicts wether the camera's goin gto try centering. -s16 newcam_yaw_target; // The yaw value the camera tries to set itself to when the centre flag is active. Is set to Mario's face angle. -f32 newcam_turnwait; // The amount of time to wait after landing before allowing the camera to turn again -f32 newcam_pan_x; -f32 newcam_pan_z; -u8 newcam_cstick_down = 0; //Just a value that triggers true when the player 2 stick is moved in 8 direction move to prevent holding it down. -u8 newcam_target; -s32 newcam_sintimer = 0; -s16 newcam_coldist; -u8 newcam_xlu = 255; -s8 newcam_stick2[2]; - -s16 newcam_sensitivityX; //How quick the camera works. -s16 newcam_sensitivityY; -s16 newcam_invertX; //Reverses movement of the camera axis. -s16 newcam_invertY; -s16 newcam_panlevel; //How much the camera sticks out a bit in the direction you're looking. -s16 newcam_aggression ; //How much the camera tries to centre itself to Mario's facing and movement. -s16 newcam_degrade = 1; -s16 newcam_analogue = 0; //Wether to accept inputs from a player 2 joystick, and then disables C button input. -s16 newcam_distance_values[] = {750,1250,2000}; -u8 newcam_distance_index = 0; -u8 newcam_active = 0; // basically the thing that governs if newcam is on. -u8 newcam_mouse = 0; -u16 newcam_mode; -u16 newcam_intendedmode = 0; // which camera mode the camera's going to try to be in when not forced into another. -u16 newcam_modeflags; - -s16 newcam_saved_mode = -1; -s16 newcam_saved_defmode = -1; - -u8 newcam_use_dpad = FALSE; -u8 newcam_has_collision = TRUE; -u8 newcam_direction_locked = FALSE; -u8 newcam_l_centering = TRUE; - extern bool gDjuiInMainMenu; -///This is called at every level initialisation. -void newcam_init(struct Camera *c, u8 isSoftReset) { - newcam_tilt = 1500; - newcam_yaw = -c->yaw+0x4000; //Mario and the camera's yaw have this offset between them. - newcam_mode = NC_MODE_NORMAL; - ///This here will dictate what modes the camera will start in at the beginning of a level. Below are some examples. +inline static s16 newcam_clamp(s16 value, s16 a, s16 b) { + return min(max(a, value), b); +} + +inline static s16 newcam_lengthdir_x(f32 length, s16 dir) { + return (s16) (length * coss(dir)); +} + +inline static s16 newcam_lengthdir_y(f32 length, s16 dir) { + return (s16) (length * sins(dir)); +} + +inline static s16 newcam_adjust_value(f32 var, f32 val, f32 limit) { + if (val > 0.f) { + return min(var + val, limit); + } + if (val < 0.f) { + return max(var + val, limit); + } + return var; +} + +inline static s32 newcam_ivrt(u8 axis) { + return ( + axis == 0 ? + (gNewCamera.invertX ? 1 : -1) : + (gNewCamera.invertY ? -1 : 1) + ); +} + +// This is called at every level initialisation. +static void newcam_init(struct Camera *c, u8 isSoftReset) { + gNewCamera.tilt = 1500; + gNewCamera.yaw = -c->yaw + 0x4000; // Mario and the camera's yaw have this offset between them. + gNewCamera.isSlide = false; + + // This here will dictate what modes the camera will start in at the beginning of a level. Below are some examples. if (gCameraUseCourseSpecificSettings && !isSoftReset) { switch (gCurrLevelNum) { - case LEVEL_BITDW: newcam_yaw = 0x4000; /*newcam_mode = NC_MODE_8D;*/ newcam_tilt = 4000; break; - case LEVEL_BITFS: newcam_yaw = 0x4000; /*newcam_mode = NC_MODE_8D;*/ newcam_tilt = 4000; break; - case LEVEL_BITS: newcam_yaw = 0x4000; /*newcam_mode = NC_MODE_8D;*/ newcam_tilt = 4000; break; - case LEVEL_WF: newcam_yaw = 0x4000; newcam_tilt = 2000; break; - case LEVEL_RR: newcam_yaw = 0x6000; newcam_tilt = 2000; break; - case LEVEL_CCM: if (gCurrAreaIndex == 1) {newcam_yaw = -0x4000; newcam_tilt = 2000; } else newcam_mode = NC_MODE_SLIDE; break; - case LEVEL_WDW: newcam_yaw = 0x2000; newcam_tilt = 3000; break; - case LEVEL_PSS: newcam_mode = NC_MODE_SLIDE; break; - case LEVEL_TTM: if (gCurrAreaIndex == 2) newcam_mode = NC_MODE_SLIDE; break; + case LEVEL_BITDW: gNewCamera.yaw = 0x4000; gNewCamera.tilt = 4000; break; + case LEVEL_BITFS: gNewCamera.yaw = 0x4000; gNewCamera.tilt = 4000; break; + case LEVEL_BITS: gNewCamera.yaw = 0x4000; gNewCamera.tilt = 4000; break; + case LEVEL_WF: gNewCamera.yaw = 0x4000; gNewCamera.tilt = 2000; break; + case LEVEL_RR: gNewCamera.yaw = 0x6000; gNewCamera.tilt = 2000; break; + case LEVEL_CCM: if (gCurrAreaIndex == 1) { gNewCamera.yaw = -0x4000; gNewCamera.tilt = 2000; } else { gNewCamera.isSlide = true; } break; + case LEVEL_WDW: gNewCamera.yaw = 0x2000; gNewCamera.tilt = 3000; break; + case LEVEL_PSS: gNewCamera.isSlide = true; break; + case LEVEL_TTM: if (gCurrAreaIndex == 2) { gNewCamera.isSlide = true; } break; } } // clear these out when entering a new level to prevent "camera mode buffering" - newcam_saved_defmode = -1; - newcam_saved_mode = -1; + gNewCamera.savedDefMode = NEWCAM_SAVED_MODE_NONE; + gNewCamera.savedMode = NEWCAM_SAVED_MODE_NONE; // this will be set in init_settings() if enabled - newcam_active = 0; - - newcam_distance = newcam_distance_target; - newcam_intendedmode = newcam_mode; - newcam_modeflags = newcam_mode; + gNewCamera.isActive = false; } -static s16 newcam_clamp(s16 value, s16 min, s16 max) { - if (value >= max) - return max; - else if (value <= min) - return min; - else - return value; -} +static void newcam_toggle(bool enabled) { -void newcam_toggle(bool enabled) { // force-disable if a demo is being played - if (gCurrDemoInput) + if (gCurrDemoInput) { enabled = false; + } - if (enabled && !newcam_active) { - newcam_active = 1; - newcam_saved_mode = gLakituState.mode; - newcam_saved_defmode = gLakituState.defMode; + if (enabled && !gNewCamera.isActive) { + gNewCamera.isActive = true; + gNewCamera.savedMode = gLakituState.mode; + gNewCamera.savedDefMode = gLakituState.defMode; gLakituState.mode = CAMERA_MODE_NEWCAM; gLakituState.defMode = CAMERA_MODE_NEWCAM; - } else if (!enabled && newcam_active) { - if (newcam_saved_mode != -1) { - gLakituState.defMode = newcam_saved_defmode; - gLakituState.mode = newcam_saved_mode; - newcam_saved_defmode = -1; - newcam_saved_mode = -1; + } else if (!enabled && gNewCamera.isActive) { + if (gNewCamera.savedMode != NEWCAM_SAVED_MODE_NONE) { + gLakituState.defMode = gNewCamera.savedDefMode; + gLakituState.mode = gNewCamera.savedMode; + gNewCamera.savedDefMode = NEWCAM_SAVED_MODE_NONE; + gNewCamera.savedMode = NEWCAM_SAVED_MODE_NONE; } - newcam_active = 0; + gNewCamera.isActive = false; } } -///These are the default settings for Puppycam. You may change them to change how they'll be set for first timers. +// These are the default settings for Puppycam. You may change them to change how they'll be set for first timers. void newcam_init_settings(void) { - newcam_sensitivityX = newcam_clamp(camera_config_get_x_sensitivity(), 1, 100) * 5; - newcam_sensitivityY = newcam_clamp(camera_config_get_y_sensitivity(), 1, 100) * 5; - newcam_aggression = newcam_clamp(camera_config_get_aggression(), 0, 100); - newcam_panlevel = newcam_clamp(camera_config_get_pan_level(), 0, 100); - newcam_invertX = (s16)camera_config_is_x_inverted(); - newcam_invertY = (s16)camera_config_is_y_inverted(); - newcam_mouse = (u8)camera_config_is_mouse_look_enabled(); - newcam_analogue = (s16)camera_config_is_analog_cam_enabled(); - newcam_degrade = (f32)camera_config_get_deceleration(); - newcam_use_dpad = (u8)camera_config_is_dpad_enabled(); - newcam_has_collision = (u8)camera_config_is_collision_enabled(); - newcam_l_centering = (u8)camera_config_get_centering(); + gNewCamera.sensitivityX = newcam_clamp(camera_config_get_x_sensitivity(), 1, 100) * 5; + gNewCamera.sensitivityY = newcam_clamp(camera_config_get_y_sensitivity(), 1, 100) * 5; + gNewCamera.panLevel = newcam_clamp(camera_config_get_pan_level(), 0, 100); + gNewCamera.aggression = newcam_clamp(camera_config_get_aggression(), 0, 100); + gNewCamera.deceleration = camera_config_get_deceleration(); + gNewCamera.invertX = camera_config_is_x_inverted(); + gNewCamera.invertY = camera_config_is_y_inverted(); + gNewCamera.isMouse = camera_config_is_mouse_look_enabled(); + gNewCamera.isAnalogue = camera_config_is_analog_cam_enabled(); + gNewCamera.useDPad = camera_config_is_dpad_enabled(); + gNewCamera.hasCollision = camera_config_is_collision_enabled(); + gNewCamera.LCentering = camera_config_get_centering(); // setup main menu camera - if (gDjuiInMainMenu) { newcam_tilt = 5; } + if (gDjuiInMainMenu) { + gNewCamera.tilt = 5; + } newcam_toggle(camera_config_is_free_cam_enabled() || gDjuiInMainMenu); } -void newcam_init_settings_override(bool override) { - newcam_sensitivityX = newcam_clamp(camera_config_get_x_sensitivity(), 1, 100) * 5; - newcam_sensitivityY = newcam_clamp(camera_config_get_y_sensitivity(), 1, 100) * 5; - newcam_aggression = newcam_clamp(camera_config_get_aggression(), 0, 100); - newcam_panlevel = newcam_clamp(camera_config_get_pan_level(), 0, 100); - newcam_invertX = (s16)camera_config_is_x_inverted(); - newcam_invertY = (s16)camera_config_is_y_inverted(); - newcam_mouse = (u8)camera_config_is_mouse_look_enabled(); - newcam_analogue = (s16)camera_config_is_analog_cam_enabled(); - newcam_degrade = (f32)camera_config_get_deceleration(); - newcam_use_dpad = (u8)camera_config_is_dpad_enabled(); - newcam_has_collision = (u8)camera_config_is_collision_enabled(); - newcam_l_centering = (u8)camera_config_get_centering(); - - // setup main menu camera - if (gDjuiInMainMenu) { newcam_tilt = 5; } - - newcam_toggle(override); -} - -/** Mathematic calculations. This stuffs so basic even *I* understand it lol -Basically, it just returns a position based on angle */ -static s16 lengthdir_x(f32 length, s16 dir) { - return (s16) (length * coss(dir)); -} -static s16 lengthdir_y(f32 length, s16 dir) { - return (s16) (length * sins(dir)); -} - -void newcam_diagnostics(void) { - print_text_fmt_int(32,192,"Lv %d",gCurrLevelNum); - print_text_fmt_int(32,176,"Area %d",gCurrAreaIndex); - print_text_fmt_int(32,160,"X %d", gMarioStates[0].pos[0]); - print_text_fmt_int(32,144,"Y %d", gMarioStates[0].pos[1]); - print_text_fmt_int(32,128,"Z %d", gMarioStates[0].pos[2]); - print_text_fmt_int(32,112,"FLAGS %d",newcam_modeflags); - print_text_fmt_int(180,112,"INTM %d",newcam_intendedmode); - print_text_fmt_int(32,96,"TILT UP %d",newcam_tilt_accel); - print_text_fmt_int(32,80,"YAW UP %d",newcam_yaw_accel); - print_text_fmt_int(32,64,"YAW %d",newcam_yaw); - print_text_fmt_int(32,48,"TILT %d",newcam_tilt); - print_text_fmt_int(32,32,"DISTANCE %d",newcam_distance); -} - -static s16 newcam_adjust_value(f32 var, f32 val, f32 max) { - if (val > 0.0f) { - var += val; - if (var > max) - var = max; - } else if (val < 0.0f) { - var += val; - if (var < max) - var = max; - } - - return var; -} - -static f32 newcam_approach_float(f32 var, f32 val, f32 inc) { - if (var < val) - return min(var + inc, val); - else - return max(var - inc, val); -} - -static s16 newcam_approach_s16(s16 var, s16 val, s16 inc) { - if (var < val) - return max(var + inc, val); - else - return min(var - inc, val); -} - -static int ivrt(u8 axis) { - if (axis == 0) { - if (newcam_invertX == 0) - return -1; - else - return 1; - } else { - if (newcam_invertY == 0) - return 1; - else - return -1; - } -} - static void newcam_rotate_button(void) { - f32 intendedXMag; - f32 intendedYMag; - // Unused section for coop - if ((newcam_modeflags & NC_FLAG_8D || newcam_modeflags & NC_FLAG_4D) && newcam_modeflags & NC_FLAG_XTURN) { - //8 directional camera rotation input for buttons. - if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_analogue == 0) { -#ifndef nosound - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - if (newcam_modeflags & NC_FLAG_8D) - newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x2000); - else - newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x4000); - newcam_centering = 1; - } else if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_analogue == 0) { -#ifndef nosound - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - if (newcam_modeflags & NC_FLAG_8D) - newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x2000); - else - newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x4000); - newcam_centering = 1; - } - // Used section for coop - } else if (newcam_modeflags & NC_FLAG_XTURN) { - //Standard camera movement - // Buzz if the camera can't move due to being locked - if (gPlayer1Controller->buttonPressed & (L_CBUTTONS | R_CBUTTONS) && newcam_direction_locked) { -#ifndef nosound - play_sound(SOUND_MENU_CAMERA_BUZZ, gGlobalSoundSource); -#endif - } - if ((gPlayer1Controller->buttonDown & L_CBUTTONS) && newcam_analogue == 0) { - newcam_yaw_accel = newcam_adjust_value(newcam_yaw_accel, -accel, -100); - } else if ((gPlayer1Controller->buttonDown & R_CBUTTONS) && newcam_analogue == 0) { - newcam_yaw_accel = newcam_adjust_value(newcam_yaw_accel, accel, 100); - } else if (!newcam_analogue) { -#ifdef noaccel - newcam_yaw_accel = 0; -#else - newcam_yaw_accel -= (newcam_yaw_accel*((f32)newcam_degrade/100)); -#endif - } + // Standard camera movement + // Buzz if the camera can't move due to being locked + if (gPlayer1Controller->buttonPressed & (L_CBUTTONS | R_CBUTTONS) && gNewCamera.directionLocked) { + play_sound(SOUND_MENU_CAMERA_BUZZ, gGlobalSoundSource); } - if (gPlayer1Controller->buttonDown & U_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) { - newcam_tilt_accel = newcam_adjust_value(newcam_tilt_accel, accel, 100); - } else if (gPlayer1Controller->buttonDown & D_CBUTTONS && newcam_modeflags & NC_FLAG_YTURN && newcam_analogue == 0) { - newcam_tilt_accel = newcam_adjust_value(newcam_tilt_accel, -accel, -100); - } else if (!newcam_analogue) { -#ifdef noaccel - newcam_tilt_accel = 0; -#else - newcam_tilt_accel -= (newcam_tilt_accel*((f32)newcam_degrade/100)); -#endif - } + if (!gNewCamera.isAnalogue) { - newcam_framessincec[0] ++; - newcam_framessincec[1] ++; - if (!newcam_direction_locked) { - if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0) { - if (newcam_framessincec[0] < 6) { - newcam_yaw_target = newcam_yaw+(ivrt(0)*0x3000); - newcam_centering = 1; -#ifndef nosound - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - } - newcam_framessincec[0] = 0; + // Yaw (C<, C>) + if ((gPlayer1Controller->buttonDown & L_CBUTTONS)) { + gNewCamera.yawAccel = newcam_adjust_value(gNewCamera.yawAccel, -NEWCAM_ACCEL, -NEWCAM_ACCEL_MAX); + } else if ((gPlayer1Controller->buttonDown & R_CBUTTONS)) { + gNewCamera.yawAccel = newcam_adjust_value(gNewCamera.yawAccel, NEWCAM_ACCEL, NEWCAM_ACCEL_MAX); + } else { + gNewCamera.yawAccel -= (gNewCamera.yawAccel * (gNewCamera.deceleration / NEWCAM_ACCEL_MAX)); } - if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && newcam_analogue == 0) { - if (newcam_framessincec[1] < 6) { - newcam_yaw_target = newcam_yaw-(ivrt(0)*0x3000); - newcam_centering = 1; -#ifndef nosound - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - } - newcam_framessincec[1] = 0; + + // Tilt (C^, Cv) + if (gPlayer1Controller->buttonDown & U_CBUTTONS) { + gNewCamera.tiltAccel = newcam_adjust_value(gNewCamera.tiltAccel, NEWCAM_ACCEL, NEWCAM_ACCEL_MAX); + } else if (gPlayer1Controller->buttonDown & D_CBUTTONS) { + gNewCamera.tiltAccel = newcam_adjust_value(gNewCamera.tiltAccel, -NEWCAM_ACCEL, -NEWCAM_ACCEL_MAX); + } else { + gNewCamera.tiltAccel -= (gNewCamera.tiltAccel * (gNewCamera.deceleration / NEWCAM_ACCEL_MAX)); } - } - - - //There's not much point in keeping this behind a check, but it wouldn't hurt, just incase any 2player shenanigans ever happen, it makes it easy to disable. - if (newcam_analogue == 1) { - //The joystick values cap at 80, so divide by 8 to get the same net result at maximum turn as the button - intendedXMag = newcam_stick2[0]*1.25; - intendedYMag = newcam_stick2[1]*1.25; - - if (ABS(newcam_stick2[0]) > 20 && newcam_modeflags & NC_FLAG_XTURN) { - if (newcam_modeflags & NC_FLAG_8D) { - if (newcam_cstick_down == 0) { - newcam_cstick_down = 1; - newcam_centering = 1; -#ifndef nosound + // Double-tap the C-buttons to quickly rotate the camera + gNewCamera.framesSinceCButtons[0]++; + gNewCamera.framesSinceCButtons[1]++; + if (!gNewCamera.directionLocked) { + if (gPlayer1Controller->buttonPressed & L_CBUTTONS) { + if (gNewCamera.framesSinceCButtons[0] < 6) { + gNewCamera.yawTarget = gNewCamera.yaw + (newcam_ivrt(0) * NEWCAM_YAW_STEP); + gNewCamera.centering = true; play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - if (newcam_stick2[0] > 20) { - if (newcam_modeflags & NC_FLAG_8D) - newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x2000); - else - newcam_yaw_target = newcam_yaw_target+(ivrt(0)*0x4000); - } else { - if (newcam_modeflags & NC_FLAG_8D) - newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x2000); - else - newcam_yaw_target = newcam_yaw_target-(ivrt(0)*0x4000); - } } - } else { - newcam_yaw_accel = newcam_adjust_value(newcam_yaw_accel,newcam_stick2[0]*0.125, intendedXMag); + gNewCamera.framesSinceCButtons[0] = 0; + } + if (gPlayer1Controller->buttonPressed & R_CBUTTONS) { + if (gNewCamera.framesSinceCButtons[1] < 6) { + gNewCamera.yawTarget = gNewCamera.yaw - (newcam_ivrt(0) * NEWCAM_YAW_STEP); + gNewCamera.centering = true; + play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); + } + gNewCamera.framesSinceCButtons[1] = 0; } - } else if (newcam_analogue) { - newcam_cstick_down = 0; - newcam_yaw_accel -= (newcam_yaw_accel*((f32)newcam_degrade/100)); } - - if (ABS(newcam_stick2[1]) > 20 && newcam_modeflags & NC_FLAG_YTURN) - newcam_tilt_accel = newcam_adjust_value(newcam_tilt_accel, newcam_stick2[1]*0.125, intendedYMag); - else if (newcam_analogue) - newcam_tilt_accel -= (newcam_tilt_accel*((f32)newcam_degrade/100)); } - if ((newcam_mouse == 1) && !gDjuiInMainMenu && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { - if (!newcam_use_dpad || !newcam_direction_locked) { - newcam_yaw += (f32)ivrt(0) * (f32)mouse_x * 16.0f * ((f32)newcam_sensitivityX / 250.0f); + // Analogue camera + // The joystick values cap at 80, so divide by 8 to get the same net result at maximum turn as the button + else { + + // Yaw + if (ABS(gNewCamera.extStick[0]) > 20) { + gNewCamera.yawAccel = newcam_adjust_value(gNewCamera.yawAccel, gNewCamera.extStick[0] * 0.125f, gNewCamera.extStick[0] * 1.25f); + } else { + gNewCamera.yawAccel -= (gNewCamera.yawAccel * (gNewCamera.deceleration / 100)); } - newcam_tilt += (f32)ivrt(1) * (f32)mouse_y * 16.0f * ((f32)newcam_sensitivityY / 250.0f); + + // Tilt + if (ABS(gNewCamera.extStick[1]) > 20) { + gNewCamera.tiltAccel = newcam_adjust_value(gNewCamera.tiltAccel, gNewCamera.extStick[1] * 0.125f, gNewCamera.extStick[1] * 1.25f); + } else { + gNewCamera.tiltAccel -= (gNewCamera.tiltAccel* (gNewCamera.deceleration / 100)); + } + } + + // Mouse control + if (gNewCamera.isMouse && !gDjuiInMainMenu && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { + if (!gNewCamera.useDPad || !gNewCamera.directionLocked) { + gNewCamera.yaw += newcam_ivrt(0) * mouse_x * 16.f * (gNewCamera.sensitivityX / 250.f); + } + gNewCamera.tilt += newcam_ivrt(1) * mouse_y * 16.f * (gNewCamera.sensitivityY / 250.f); } // Dpad behaviors - if (newcam_use_dpad) { + if (gNewCamera.useDPad) { + // Make dpad up head to the nearest cardinal direction if (gPlayer1Controller->buttonDown & U_JPAD) { - newcam_yaw = snap_to_45_degrees(newcam_yaw); - newcam_yaw_accel = snap_to_45_degrees(newcam_yaw_accel); + gNewCamera.yaw = snap_to_45_degrees(gNewCamera.yaw); + gNewCamera.yawAccel = snap_to_45_degrees(gNewCamera.yawAccel); } + // Make dpad left/right increment 45 degrees else if (gPlayer1Controller->buttonPressed & L_JPAD) { - newcam_yaw += ivrt(0)*DEGREES(45); -#ifndef nosound + gNewCamera.yaw += newcam_ivrt(0) * DEGREES(45); play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif - } - else if (gPlayer1Controller->buttonPressed & R_JPAD) { - newcam_yaw -= ivrt(0)*DEGREES(45); -#ifndef nosound + } else if (gPlayer1Controller->buttonPressed & R_JPAD) { + gNewCamera.yaw -= newcam_ivrt(0) * DEGREES(45); play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); -#endif } + // Make dpad down lock the current camera direction else if (gPlayer1Controller->buttonPressed & D_JPAD) { - newcam_direction_locked = !newcam_direction_locked; + gNewCamera.directionLocked = !gNewCamera.directionLocked; } } - if (newcam_use_dpad && newcam_direction_locked) { - newcam_yaw_accel = 0; + if (gNewCamera.useDPad && gNewCamera.directionLocked) { + gNewCamera.yawAccel = 0; } } +static f32 newcam_get_distance_target() { + gNewCamera.distanceTargetIndex = newcam_clamp(gNewCamera.distanceTargetIndex, 0, NEWCAM_NUM_DISTANCES - 1); + return NEWCAM_DISTANCES[gNewCamera.distanceTargetIndex]; +} + static void newcam_zoom_button(void) { if (gDjuiInMainMenu) { - newcam_distance = 750; - newcam_distance_target = 750; + gNewCamera.distance = NEWCAM_DISTANCES[0]; + gNewCamera.distanceTargetIndex = 0; return; } - - //Smoothly move the camera to the new spot. - if (newcam_distance > newcam_distance_target) { - newcam_distance -= 250; - if (newcam_distance < newcam_distance_target) - newcam_distance = newcam_distance_target; + + f32 distanceTarget = newcam_get_distance_target(); + + // Smoothly move the camera to the new spot. + if (gNewCamera.distance > distanceTarget) { + gNewCamera.distance = max(gNewCamera.distance - NEWCAM_DISTANCE_INC, distanceTarget); } - if (newcam_distance < newcam_distance_target) { - newcam_distance += 250; - if (newcam_distance > newcam_distance_target) - newcam_distance = newcam_distance_target; + if (gNewCamera.distance < distanceTarget) { + gNewCamera.distance = min(gNewCamera.distance + NEWCAM_DISTANCE_INC, distanceTarget); } - if (newcam_l_centering && (gPlayer1Controller->buttonDown & L_TRIG) && (newcam_modeflags & NC_FLAG_ZOOM)) { - //When you press L, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time. - newcam_yaw_target = -gMarioStates[0].faceAngle[1]-0x4000; - newcam_centering = 1; - } else if (gPlayer1Controller->buttonPressed & R_TRIG && newcam_modeflags & NC_FLAG_XTURN) { - //Each time the player presses R, but NOT L the camera zooms out more, until it hits the limit and resets back to close view. -#ifndef nosound + // When you press L, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time. + if (gNewCamera.LCentering && (gPlayer1Controller->buttonDown & L_TRIG)) { + gNewCamera.yawTarget = -gMarioState->faceAngle[1] - 0x4000; + gNewCamera.centering = true; + } + + // Each time the player presses R, but NOT L the camera zooms out more, until it hits the limit and resets back to close view. + else if (gPlayer1Controller->buttonPressed & R_TRIG) { play_sound(SOUND_MENU_CLICK_CHANGE_VIEW, gGlobalSoundSource); -#endif - - if (newcam_distance_target == newcam_distance_values[0]) { - newcam_distance_target = newcam_distance_values[1]; - newcam_distance_index = 1; - } else if (newcam_distance_target == newcam_distance_values[1]) { - newcam_distance_target = newcam_distance_values[2]; - newcam_distance_index = 2; - } else { - newcam_distance_target = newcam_distance_values[0]; - newcam_distance_index = 0; - } + gNewCamera.distanceTargetIndex = (gNewCamera.distanceTargetIndex + 1) % NEWCAM_NUM_DISTANCES; } - if (newcam_centering && newcam_modeflags & NC_FLAG_XTURN) { - newcam_yaw = approach_s16_symmetric(newcam_yaw,newcam_yaw_target,0x800); - if (newcam_yaw == newcam_yaw_target) - newcam_centering = 0; + if (gNewCamera.centering) { + gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, gNewCamera.yawTarget, 0x800); + if (gNewCamera.yaw == gNewCamera.yawTarget) { + gNewCamera.centering = false; + } } else { - newcam_yaw_target = newcam_yaw; + gNewCamera.yawTarget = gNewCamera.yaw; } } static void newcam_update_values(void) { - //For tilt, this just limits it so it doesn't go further than 90 degrees either way. 90 degrees is actually 16384, but can sometimes lead to issues, so I just leave it shy of 90. - u8 waterflag = 0; - u8 centering = 0; - u8 ycentering = 1; + bool centering = false; + bool ycentering = true; - if (newcam_modeflags & NC_FLAG_XTURN) - newcam_yaw -= ((newcam_yaw_accel*(newcam_sensitivityX/10))*ivrt(0)); - if (((newcam_tilt <= 0x3000) && (newcam_tilt >= -0x3000)) && newcam_modeflags & NC_FLAG_YTURN) - newcam_tilt += ((newcam_tilt_accel*ivrt(1))*(newcam_sensitivityY/10)); + // Update yaw and tilt + gNewCamera.yaw -= gNewCamera.yawAccel * newcam_ivrt(0) * (gNewCamera.sensitivityX / 10); + gNewCamera.tilt = newcam_clamp(gNewCamera.tilt + gNewCamera.tiltAccel * newcam_ivrt(1) * (gNewCamera.sensitivityY / 10), -NEWCAM_TILT_LIMIT, +NEWCAM_TILT_LIMIT); - if (newcam_tilt > 0x3000) - newcam_tilt = 0x3000; - if (newcam_tilt < -0x3000 && gMarioStates[0].pos[1] - gMarioStates[0].floorHeight > 20) - newcam_tilt = -0x3000; - if (newcam_tilt < -0x3000 && gMarioStates[0].pos[1] - gMarioStates[0].floorHeight < 20) - newcam_tilt = -0x3000; - - if (newcam_turnwait > 0 && gMarioStates[0].vel[1] == 0) { - newcam_turnwait -= 1; - if (newcam_turnwait < 0) - newcam_turnwait = 0; + // 10 frames after landing, progressively center the camera behind Mario when he's moving + // This effect can be negated by setting `aggression` to 0 + if (gNewCamera.turnWait > 0 && gMarioState->vel[1] == 0) { + gNewCamera.turnWait--; + } else if (gMarioState->intendedMag > 0 && gMarioState->vel[1] == 0) { + gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->faceAngle[1] - 0x4000, ((gNewCamera.aggression * (ABS(gPlayer1Controller->rawStickX / 10.f))) * (gMarioState->forwardVel / 32.f))); } else { - if (gMarioStates[0].intendedMag > 0 && gMarioStates[0].vel[1] == 0 && newcam_modeflags & NC_FLAG_XTURN && !(newcam_modeflags & NC_FLAG_8D) && !(newcam_modeflags & NC_FLAG_4D)) - newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioStates[0].faceAngle[1]-0x4000,((newcam_aggression*(ABS(gPlayer1Controller->rawStickX/10)))*(gMarioStates[0].forwardVel/32)))); - else - newcam_turnwait = 10; + gNewCamera.turnWait = 10; } - if (newcam_modeflags & NC_FLAG_SLIDECORRECT) { - switch (gMarioStates[0].action) { - case ACT_BUTT_SLIDE: if (gMarioStates[0].forwardVel > 8) centering = 1; ycentering = 0; break; - case ACT_STOMACH_SLIDE: if (gMarioStates[0].forwardVel > 8) centering = 1; ycentering = 0; break; - case ACT_HOLD_BUTT_SLIDE: if (gMarioStates[0].forwardVel > 8) centering = 1; ycentering = 0; break; - case ACT_HOLD_STOMACH_SLIDE: if (gMarioStates[0].forwardVel > 8) centering = 1; ycentering = 0; break; - } + // During slide actions in slide levels, force centering + if (gNewCamera.isSlide && ( + gMarioState->action == ACT_BUTT_SLIDE || + gMarioState->action == ACT_STOMACH_SLIDE || + gMarioState->action == ACT_HOLD_BUTT_SLIDE || + gMarioState->action == ACT_HOLD_STOMACH_SLIDE) + ) { + centering = (gMarioState->forwardVel > 8); + ycentering = false; } - if ((gMarioStates[0].action & ACT_FLAG_FLYING) == ACT_FLAG_FLYING) { - centering = 1; + // Force centering when flying + if ((gMarioState->action & ACT_FLAG_FLYING) == ACT_FLAG_FLYING) { + centering = true; } + // Force centering when changing action + // Place the camera behind Mario during the ACT_SHOT_FROM_CANNON action static u32 sLastAction = 0; - static u8 sForceCentering = 10; - if (sLastAction != gMarioStates[0].action) { - sLastAction = gMarioStates[0].action; - sForceCentering = 1; - switch (gMarioStates[0].action) { + static bool sForceCentering = false; + if (sLastAction != gMarioState->action) { + sLastAction = gMarioState->action; + sForceCentering = true; + switch (gMarioState->action) { case ACT_SHOT_FROM_CANNON: - newcam_yaw = -gMarioStates[0].faceAngle[1]-0x4000; + gNewCamera.yaw = -gMarioState->faceAngle[1] - 0x4000; break; } } + // WTF is this if (centering) { - if (fabs(newcam_yaw_accel) > 32 || fabs(newcam_tilt_accel) > 32) { - sForceCentering = 0; + if (fabs(gNewCamera.yawAccel) > 32 || fabs(gNewCamera.tiltAccel) > 32) { + sForceCentering = false; + } + if (!sForceCentering) { + centering = false; } - if (sForceCentering) { waterflag = 1; } } - if (gMarioStates[0].action & ACT_FLAG_SWIMMING) { - if (gMarioStates[0].forwardVel > 2) - waterflag = 1; + // Force centering during non-still swimming actions + if (gMarioState->action & ACT_FLAG_SWIMMING && gMarioState->forwardVel > 2) { + centering = true; } - if (waterflag && newcam_modeflags & NC_FLAG_XTURN) { - newcam_yaw = (approach_s16_symmetric(newcam_yaw,-gMarioStates[0].faceAngle[1]-0x4000,(gMarioStates[0].forwardVel*128))); - if ((signed)gMarioStates[0].forwardVel > 1 && ycentering) - newcam_tilt = (approach_s16_symmetric(newcam_tilt,(-gMarioStates[0].faceAngle[0]*0.8)+3000,(gMarioStates[0].forwardVel*32))); - else - newcam_tilt = (approach_s16_symmetric(newcam_tilt,3000,32)); + if (centering) { + gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->faceAngle[1] - 0x4000, gMarioState->forwardVel * 128); + if (gMarioState->forwardVel > 1 && ycentering) { + gNewCamera.tilt = approach_s16_symmetric(gNewCamera.tilt, (-gMarioState->faceAngle[0] * 0.8f) + NEWCAM_TILT_CENTERING, gMarioState->forwardVel * 32); + } else { + gNewCamera.tilt = approach_s16_symmetric(gNewCamera.tilt, NEWCAM_TILT_CENTERING, 32); + } } } static void newcam_collision(void) { + // check if we can see player Vec3f up = { 0, 1, 0 }; Vec3f mainRay = { - newcam_pos[0]-newcam_lookat[0], - newcam_pos[1]-newcam_lookat[1], - newcam_pos[2]-newcam_lookat[2], + gNewCamera.pos[0] - gNewCamera.lookAt[0], + gNewCamera.pos[1] - gNewCamera.lookAt[1], + gNewCamera.pos[2] - gNewCamera.lookAt[2], }; Vec3f sideway; vec3f_normalize(mainRay); vec3f_cross(sideway, mainRay, up); - f32 checkWidth = 75; - f32 checkHeight = 90; - + // Checks collision with left, up and right direction vectors bool allhit = true; - for (f32 x = -1; x <= 1; x++) { - for (f32 y = 0; y <= 1; y++) { - if (fabs(x) + fabs(y) != 1) { continue; } - Vec3f offset = { - sideway[0] * x * checkWidth, - -checkHeight / 2 + y * checkHeight, - sideway[2] * x * checkWidth, - }; + for (s32 i = 0; i != 3; ++i) { + f32 x = (f32) (-1 + i); // -1, 0, 1 + f32 y = (f32) (i % 2); // 0, 1, 0 + Vec3f offset = { + sideway[0] * x * NEWCAM_COLLISION_CHECK_WIDTH, + -NEWCAM_COLLISION_CHECK_HEIGHT / 2 + y * NEWCAM_COLLISION_CHECK_HEIGHT, + sideway[2] * x * NEWCAM_COLLISION_CHECK_WIDTH, + }; - if (x != 0) { - struct Surface* surf; - Vec3f hitpos; - Vec3f move = { - offset[0] * 1.2f, - offset[1], - offset[2] * 1.2f, - }; - find_surface_on_ray(newcam_pos_target, move, &surf, hitpos, 3.0f); - vec3f_copy(offset, hitpos); - vec3f_sub(offset, newcam_pos_target); - if (surf) { - offset[0] *= 0; - offset[2] *= 0; - } - } - - Vec3f camray = { - newcam_pos[0] - newcam_lookat[0] - offset[0], - newcam_pos[1] - newcam_lookat[1] - offset[1], - newcam_pos[2] - newcam_lookat[2] - offset[2], - }; - - Vec3f camorig = { - newcam_pos_target[0] + offset[0], - newcam_pos_target[1] + offset[1], - newcam_pos_target[2] + offset[2], - }; - - struct Surface* surf; + if (x != 0) { + struct Surface *surf = NULL; Vec3f hitpos; - find_surface_on_ray(camorig, camray, &surf, hitpos, 3.0f); - - if (surf == NULL) { - allhit = false; + Vec3f move = { + offset[0] * 1.2f, + offset[1], + offset[2] * 1.2f, + }; + find_surface_on_ray(gNewCamera.posTarget, move, &surf, hitpos, 3.f); + vec3f_copy(offset, hitpos); + vec3f_sub(offset, gNewCamera.posTarget); + if (surf) { + offset[0] = 0; + offset[2] = 0; } } + + Vec3f camray = { + gNewCamera.pos[0] - gNewCamera.lookAt[0] - offset[0], + gNewCamera.pos[1] - gNewCamera.lookAt[1] - offset[1], + gNewCamera.pos[2] - gNewCamera.lookAt[2] - offset[2], + }; + + Vec3f camorig = { + gNewCamera.posTarget[0] + offset[0], + gNewCamera.posTarget[1] + offset[1], + gNewCamera.posTarget[2] + offset[2], + }; + + struct Surface *surf = NULL; + Vec3f hitpos; + find_surface_on_ray(camorig, camray, &surf, hitpos, 3.f); + if (surf == NULL) { + allhit = false; + } } Vec3f camdir = { - newcam_pos[0]-newcam_lookat[0], - newcam_pos[1]-newcam_lookat[1], - newcam_pos[2]-newcam_lookat[2], + gNewCamera.pos[0] - gNewCamera.lookAt[0], + gNewCamera.pos[1] - gNewCamera.lookAt[1], + gNewCamera.pos[2] - gNewCamera.lookAt[2], }; if (allhit) { struct Surface *surf = NULL; Vec3f hitpos; - - find_surface_on_ray(newcam_lookat, camdir, &surf, hitpos, 3.0f); + find_surface_on_ray(gNewCamera.lookAt, camdir, &surf, hitpos, 3.f); if (surf) { // offset the hit pos by the hit normal @@ -671,207 +484,152 @@ static void newcam_collision(void) { offset[0] = surf->normal.x; offset[1] = surf->normal.y; offset[2] = surf->normal.z; - vec3f_mul(offset, 5.0f); + vec3f_mul(offset, 5.f); vec3f_add(hitpos, offset); - newcam_pos[0] = hitpos[0]; - newcam_pos[1] = hitpos[1]; - newcam_pos[2] = hitpos[2]; - newcam_pan_x = 0; - newcam_pan_z = 0; + gNewCamera.pos[0] = hitpos[0]; + gNewCamera.pos[1] = hitpos[1]; + gNewCamera.pos[2] = hitpos[2]; + gNewCamera.panX = 0; + gNewCamera.panZ = 0; } - - newcam_coldist = vec3f_dist(newcam_pos_target, hitpos); - } else { - newcam_pos[0] = newcam_lookat[0] + camdir[0]; - newcam_pos[1] = newcam_lookat[1] + camdir[1]; - newcam_pos[2] = newcam_lookat[2] + camdir[2]; - newcam_coldist = vec3f_length(camdir); + gNewCamera.pos[0] = gNewCamera.lookAt[0] + camdir[0]; + gNewCamera.pos[1] = gNewCamera.lookAt[1] + camdir[1]; + gNewCamera.pos[2] = gNewCamera.lookAt[2] + camdir[2]; } } static void newcam_set_pan(void) { if (gDjuiInMainMenu) { - newcam_pan_x = 0; - newcam_pan_z = 0; + gNewCamera.panX = 0; + gNewCamera.panZ = 0; return; } - //Apply panning values based on Mario's direction. - if (gMarioStates[0].action != ACT_HOLDING_BOWSER && gMarioStates[0].action != ACT_SLEEPING && gMarioStates[0].action != ACT_START_SLEEPING) { - approach_f32_asymptotic_bool(&newcam_pan_x, lengthdir_x((160*newcam_panlevel)/100, -gMarioStates[0].faceAngle[1]-0x4000), 0.05); - approach_f32_asymptotic_bool(&newcam_pan_z, lengthdir_y((160*newcam_panlevel)/100, -gMarioStates[0].faceAngle[1]-0x4000), 0.05); + // Apply panning values based on Mario's direction. + if (gMarioState->action != ACT_HOLDING_BOWSER && + gMarioState->action != ACT_SLEEPING && + gMarioState->action != ACT_START_SLEEPING + ) { + approach_f32_asymptotic_bool(&gNewCamera.panX, newcam_lengthdir_x((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->faceAngle[1] - 0x4000), 0.05f); + approach_f32_asymptotic_bool(&gNewCamera.panZ, newcam_lengthdir_y((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->faceAngle[1] - 0x4000), 0.05f); } else { - approach_f32_asymptotic_bool(&newcam_pan_x, 0, 0.05); - approach_f32_asymptotic_bool(&newcam_pan_z, 0, 0.05); + approach_f32_asymptotic_bool(&gNewCamera.panX, 0, 0.05f); + approach_f32_asymptotic_bool(&gNewCamera.panZ, 0, 0.05f); } - newcam_pan_x = newcam_pan_x*(min(newcam_distance/newcam_distance_target,1)); - newcam_pan_z = newcam_pan_z*(min(newcam_distance/newcam_distance_target,1)); + f32 distanceTarget = newcam_get_distance_target(); + gNewCamera.panX = gNewCamera.panX * min(gNewCamera.distance / distanceTarget, 1); + gNewCamera.panZ = gNewCamera.panZ * min(gNewCamera.distance / distanceTarget, 1); } static void newcam_level_bounds(void) { - u8 hasMinY = FALSE; - f32 minY = 0; - get_area_minimum_y(&hasMinY, &minY); - if (!hasMinY) { return; } - newcam_pos[1] = MAX(newcam_pos[1], minY); + if (gCameraUseCourseSpecificSettings) { + u8 hasMinY = FALSE; + f32 minY = 0; + get_area_minimum_y(&hasMinY, &minY); + if (hasMinY) { + gNewCamera.pos[1] = max(gNewCamera.pos[1], minY); + } + } } static void newcam_position_cam(void) { f32 floorY = 0; f32 floorY2 = 0; - s16 shakeX; - s16 shakeY; - - if (!(gMarioStates[0].action & ACT_FLAG_SWIMMING) && newcam_modeflags & NC_FLAG_FOCUSY && newcam_modeflags & NC_FLAG_POSY) + if (!(gMarioState->action & ACT_FLAG_SWIMMING)) { calc_y_to_curr_floor(&floorY, 1.f, 200.f, &floorY2, 0.9f, 200.f); - - newcam_update_values(); - shakeX = gLakituState.shakeMagnitude[1]; - shakeY = gLakituState.shakeMagnitude[0]; - //Fetch Mario's current position. Not hardcoded just for the sake of flexibility, though this specific bit is temp, because it won't always want to be focusing on Mario. - newcam_pos_target[0] = gMarioStates[0].pos[0]; - newcam_pos_target[1] = gMarioStates[0].pos[1]+newcam_extheight; - newcam_pos_target[2] = gMarioStates[0].pos[2]; - //These will set the position of the camera to where Mario is supposed to be, minus adjustments for where the camera should be, on top of. - if (newcam_modeflags & NC_FLAG_POSX) - newcam_pos[0] = newcam_pos_target[0]+lengthdir_x(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY); - if (newcam_modeflags & NC_FLAG_POSZ) - newcam_pos[2] = newcam_pos_target[2]+lengthdir_y(lengthdir_x(newcam_distance,newcam_tilt+shakeX),newcam_yaw+shakeY); - if (newcam_modeflags & NC_FLAG_POSY) - newcam_pos[1] = newcam_pos_target[1]+lengthdir_y(newcam_distance,newcam_tilt+gLakituState.shakeMagnitude[0])+floorY; - if ((newcam_modeflags & NC_FLAG_FOCUSX) && (newcam_modeflags & NC_FLAG_FOCUSY) && (newcam_modeflags & NC_FLAG_FOCUSZ)) - newcam_set_pan(); - //Set where the camera wants to be looking at. This is almost always the place it's based off, too. - if (newcam_modeflags & NC_FLAG_FOCUSX) - newcam_lookat[0] = newcam_pos_target[0]-newcam_pan_x; - if (newcam_modeflags & NC_FLAG_FOCUSY) - newcam_lookat[1] = newcam_pos_target[1]+floorY2; - if (newcam_modeflags & NC_FLAG_FOCUSZ) - newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z; - - newcam_level_bounds(); - if (newcam_has_collision && newcam_modeflags & NC_FLAG_COLLISION) { - newcam_collision(); } -} + newcam_update_values(); + s16 shakeX = gLakituState.shakeMagnitude[1]; + s16 shakeY = gLakituState.shakeMagnitude[0]; -//Nested if's baybeeeee -UNUSED static void newcam_find_fixed(void) { - u8 i = 0; - newcam_mode = newcam_intendedmode; - newcam_modeflags = newcam_mode; - for (i = 0; i < sizeof(newcam_fixedcam) / sizeof(struct newcam_hardpos); i++) { - if (newcam_fixedcam[i].newcam_hard_levelID == gCurrLevelNum && newcam_fixedcam[i].newcam_hard_areaID == gCurrAreaIndex) { - if ((newcam_pos_target[0] > newcam_fixedcam[i].newcam_hard_X1) - && (newcam_pos_target[0] < newcam_fixedcam[i].newcam_hard_X2) - && (newcam_pos_target[1] > newcam_fixedcam[i].newcam_hard_Y1) - && (newcam_pos_target[1] < newcam_fixedcam[i].newcam_hard_Y2) - && (newcam_pos_target[2] > newcam_fixedcam[i].newcam_hard_Z1) - && (newcam_pos_target[2] < newcam_fixedcam[i].newcam_hard_Z2)) { - if (newcam_fixedcam[i].newcam_hard_permaswap) - newcam_intendedmode = newcam_fixedcam[i].newcam_hard_modeset; - newcam_mode = newcam_fixedcam[i].newcam_hard_modeset; - newcam_modeflags = newcam_mode; + // Fetch Mario's current position. + // Not hardcoded just for the sake of flexibility, though this specific bit is temp, + // because it won't always want to be focusing on Mario. + gNewCamera.posTarget[0] = gMarioState->pos[0]; + gNewCamera.posTarget[1] = gMarioState->pos[1] + NEWCAM_MARIO_HEIGHT; + gNewCamera.posTarget[2] = gMarioState->pos[2]; - if (newcam_fixedcam[i].newcam_hard_camX != 32767 && !(newcam_modeflags & NC_FLAG_POSX)) - newcam_pos[0] = newcam_fixedcam[i].newcam_hard_camX; - if (newcam_fixedcam[i].newcam_hard_camY != 32767 && !(newcam_modeflags & NC_FLAG_POSY)) - newcam_pos[1] = newcam_fixedcam[i].newcam_hard_camY; - if (newcam_fixedcam[i].newcam_hard_camZ != 32767 && !(newcam_modeflags & NC_FLAG_POSZ)) - newcam_pos[2] = newcam_fixedcam[i].newcam_hard_camZ; + // These will set the position of the camera to where Mario is supposed to be, + // minus adjustments for where the camera should be, on top of. + gNewCamera.pos[0] = gNewCamera.posTarget[0] + newcam_lengthdir_x(newcam_lengthdir_x(gNewCamera.distance, gNewCamera.tilt + shakeX), gNewCamera.yaw + shakeY); + gNewCamera.pos[2] = gNewCamera.posTarget[2] + newcam_lengthdir_y(newcam_lengthdir_x(gNewCamera.distance, gNewCamera.tilt + shakeX), gNewCamera.yaw + shakeY); + gNewCamera.pos[1] = gNewCamera.posTarget[1] + newcam_lengthdir_y(gNewCamera.distance, gNewCamera.tilt + shakeY) + floorY; + newcam_set_pan(); - if (newcam_fixedcam[i].newcam_hard_lookX != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSX)) - newcam_lookat[0] = newcam_fixedcam[i].newcam_hard_lookX; - if (newcam_fixedcam[i].newcam_hard_lookY != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSY)) - newcam_lookat[1] = newcam_fixedcam[i].newcam_hard_lookY; - if (newcam_fixedcam[i].newcam_hard_lookZ != 32767 && !(newcam_modeflags & NC_FLAG_FOCUSZ)) - newcam_lookat[2] = newcam_fixedcam[i].newcam_hard_lookZ; + // Set where the camera wants to be looking at. + // This is almost always the place it's based off, too. + gNewCamera.lookAt[0] = gNewCamera.posTarget[0] - gNewCamera.panX; + gNewCamera.lookAt[1] = gNewCamera.posTarget[1] + floorY2; + gNewCamera.lookAt[2] = gNewCamera.posTarget[2] - gNewCamera.panZ; - newcam_yaw = atan2s(newcam_pos[0]-newcam_pos_target[0],newcam_pos[2]-newcam_pos_target[2]); - } - } + newcam_level_bounds(); + if (gNewCamera.hasCollision) { + newcam_collision(); } } static void newcam_apply_values(struct Camera *c) { - c->pos[0] = newcam_pos[0]; - c->pos[1] = newcam_pos[1]; - c->pos[2] = newcam_pos[2]; + c->pos[0] = gNewCamera.pos[0]; + c->pos[1] = gNewCamera.pos[1]; + c->pos[2] = gNewCamera.pos[2]; - c->focus[0] = newcam_lookat[0]; - c->focus[1] = newcam_lookat[1]; - c->focus[2] = newcam_lookat[2]; + c->focus[0] = gNewCamera.lookAt[0]; + c->focus[1] = gNewCamera.lookAt[1]; + c->focus[2] = gNewCamera.lookAt[2]; - gLakituState.pos[0] = newcam_pos[0]; - gLakituState.pos[1] = newcam_pos[1]; - gLakituState.pos[2] = newcam_pos[2]; + gLakituState.pos[0] = gNewCamera.pos[0]; + gLakituState.pos[1] = gNewCamera.pos[1]; + gLakituState.pos[2] = gNewCamera.pos[2]; - gLakituState.focus[0] = newcam_lookat[0]; - gLakituState.focus[1] = newcam_lookat[1]; - gLakituState.focus[2] = newcam_lookat[2]; + gLakituState.focus[0] = gNewCamera.lookAt[0]; + gLakituState.focus[1] = gNewCamera.lookAt[1]; + gLakituState.focus[2] = gNewCamera.lookAt[2]; - c->yaw = -newcam_yaw+0x4000; - gLakituState.yaw = -newcam_yaw+0x4000; + c->yaw = -gNewCamera.yaw + 0x4000; + gLakituState.yaw = -gNewCamera.yaw + 0x4000; - //Adds support for wing mario tower - if (gMarioStates[0].floor != NULL) { - if (gMarioStates[0].floor->type == SURFACE_LOOK_UP_WARP) { - if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 0x18) >= gLevelValues.wingCapLookUpReq) { - if (newcam_tilt < -8000 && gMarioStates[0].forwardVel == 0 && sCurrPlayMode != PLAY_MODE_PAUSED) { - level_trigger_warp(gMarioState, 1); - } - } - } + // Adds support for wing mario tower + if (gNewCamera.tilt < -8000 && + sCurrPlayMode != PLAY_MODE_PAUSED && + gMarioState->floor != NULL && + gMarioState->floor->type == SURFACE_LOOK_UP_WARP && + gMarioState->forwardVel == 0 && + save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, COURSE_COUNT - 1) >= gLevelValues.wingCapLookUpReq) + { + level_trigger_warp(gMarioState, 1); } } -//If puppycam gets too close to its target, start fading it out so you don't see the inside of it. -void newcam_fade_target_closeup(void) { - if (newcam_coldist <= 250 && (newcam_coldist-150)*2.55f < 255) { - if ((newcam_coldist-150)*2.55f > 0) - newcam_xlu = (newcam_coldist-150)*2.55f; - else - newcam_xlu = 0; +// The ingame cutscene system is such a spaghetti mess I actually have to resort to something as stupid as this to cover every base. +static void newcam_update_camera_yaw(struct Camera *c, bool useMarioYaw) { + if (useMarioYaw) { + gNewCamera.yaw = -gMarioState->faceAngle[1] - 0x4000; } else { - newcam_xlu = 255; + gNewCamera.yaw = -c->yaw + 0x4000; } } -//The ingame cutscene system is such a spaghetti mess I actually have to resort to something as stupid as this to cover every base. -void newcam_apply_outside_values(struct Camera *c, u8 bit) { - if (bit) - newcam_yaw = -gMarioStates[0].faceAngle[1]-0x4000; - else - newcam_yaw = -c->yaw+0x4000; -} - static void newcam_stick_input(void) { - newcam_stick2[0] = gPlayer1Controller->extStickX; - newcam_stick2[1] = gPlayer1Controller->extStickY; + gNewCamera.extStick[0] = gPlayer1Controller->extStickX; + gNewCamera.extStick[1] = gPlayer1Controller->extStickY; } -//Main loop. -void newcam_loop(struct Camera *c) { +// Main loop. +static void newcam_loop(struct Camera *c) { if (sCurrPlayMode != PLAY_MODE_PAUSED) { newcam_stick_input(); newcam_rotate_button(); newcam_zoom_button(); } else { - newcam_yaw_accel *= 0.6f; - newcam_tilt_accel *= 0.6f; + gNewCamera.yawAccel *= 0.6f; + gNewCamera.tiltAccel *= 0.6f; } newcam_position_cam(); - //newcam_find_fixed(); - if (gMarioObject) + if (gMarioObject) { newcam_apply_values(c); - newcam_fade_target_closeup(); - - //Just some visual information on the values of the camera. utilises ifdef because it's better at runtime. -#ifdef NEWCAM_DEBUG - newcam_diagnostics(); -#endif // NEWCAM_DEBUG + } } diff --git a/src/game/camera.c b/src/game/camera.c index 6558a0ed5..5efaf8818 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -3235,7 +3235,7 @@ void update_camera(struct Camera *c) { sCButtonsPressed = find_c_buttons_pressed(sCButtonsPressed, gPlayer1Controller->buttonPressed,gPlayer1Controller->buttonDown); } - if (gMarioStates[0].action == ACT_SHOT_FROM_CANNON && newcam_active) { + if (gMarioStates[0].action == ACT_SHOT_FROM_CANNON && gNewCamera.isActive) { gMarioStates[0].area->camera->mode = CAMERA_MODE_NEWCAM; gLakituState.mode = CAMERA_MODE_NEWCAM; } @@ -5794,7 +5794,7 @@ void set_camera_mode_8_directions(struct Camera *c) { s8DirModeYawOffset = 0; } - if (newcam_active == 1) { + if (gNewCamera.isActive) { c->mode = CAMERA_MODE_NEWCAM; } } @@ -5818,7 +5818,7 @@ void set_camera_mode_close_cam(u8 *mode) { *mode = CAMERA_MODE_CLOSE; } - if (newcam_active == 1) { + if (gNewCamera.isActive) { *mode = CAMERA_MODE_NEWCAM; } } @@ -5847,7 +5847,7 @@ void set_camera_mode_radial(struct Camera *c, s16 transitionTime) { sModeOffsetYaw = 0; } - if (newcam_active == 1) { + if (gNewCamera.isActive) { c->mode = CAMERA_MODE_NEWCAM; } } @@ -7306,7 +7306,7 @@ void update_camera_yaw(struct Camera *c) { if (!c) { return; } c->nextYaw = calculate_yaw(c->focus, c->pos); c->yaw = c->nextYaw; - newcam_apply_outside_values(c,0); + newcam_update_camera_yaw(c, false); } void cutscene_reset_spline(void) { @@ -10485,7 +10485,7 @@ BAD_RETURN(s32) cutscene_sliding_doors_follow_mario(struct Camera *c) { BAD_RETURN(s32) cutscene_sliding_doors_open(struct Camera *c) { UNUSED u32 pad[2]; - newcam_apply_outside_values(c,1); + newcam_update_camera_yaw(c, true); reset_pan_distance(c); cutscene_event(cutscene_sliding_doors_open_start, c, 0, 8); cutscene_event(cutscene_sliding_doors_open_set_cvars, c, 8, 8); @@ -10698,7 +10698,7 @@ BAD_RETURN(s32) cutscene_unused_exit_focus_mario(struct Camera *c) { */ BAD_RETURN(s32) cutscene_exit_painting_end(struct Camera *c) { if (!c) { return; } - if (newcam_active == 1) { + if (gNewCamera.isActive) { c->mode = CAMERA_MODE_NEWCAM; } else { c->mode = CAMERA_MODE_CLOSE; diff --git a/src/game/hud.c b/src/game/hud.c index 4059d756f..f136d9650 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -17,6 +17,7 @@ #include "save_file.h" #include "print.h" #include "hardcoded.h" +#include "bettercamera.h" #include "pc/configfile.h" #include "pc/network/network.h" #include "pc/utils/misc.h" @@ -563,18 +564,11 @@ void render_hud_camera_status(void) { } if (gLakituState.mode == CAMERA_MODE_NEWCAM) { - extern u8 newcam_direction_locked; - extern u8 newcam_distance_index; - sCameraHUD.status = newcam_direction_locked ? CAM_STATUS_FIXED : CAM_STATUS_LAKITU; - switch (newcam_distance_index) { - case 0: - sCameraHUD.status |= CAM_STATUS_C_UP; - break; - case 1: - break; - case 2: - sCameraHUD.status |= CAM_STATUS_C_DOWN; - break; + sCameraHUD.status = gNewCamera.directionLocked ? CAM_STATUS_FIXED : CAM_STATUS_LAKITU; + switch (gNewCamera.distanceTargetIndex) { + case 0: sCameraHUD.status |= CAM_STATUS_C_UP; break; + case 1: break; + case 2: sCameraHUD.status |= CAM_STATUS_C_DOWN; break; } } diff --git a/src/game/mario.c b/src/game/mario.c index fb9ee84c2..5075b5169 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1498,7 +1498,7 @@ void update_mario_joystick_inputs(struct MarioState *m) { } else if (get_first_person_enabled()) { m->intendedYaw = atan2s(-controller->stickY, controller->stickX) + gLakituState.yaw; } else { - m->intendedYaw = atan2s(-controller->stickY, controller->stickX) - newcam_yaw + 0x4000; + m->intendedYaw = atan2s(-controller->stickY, controller->stickX) - gNewCamera.yaw + 0x4000; } m->input |= INPUT_NONZERO_ANALOG; } else { diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 5bf9454b1..a9594baef 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -1869,7 +1869,7 @@ s32 act_shot_from_cannon(struct MarioState *m) { set_mario_action(m, ACT_DIVE_SLIDE, 0); m->faceAngle[0] = 0; if (allowCameraChange) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -1890,7 +1890,7 @@ s32 act_shot_from_cannon(struct MarioState *m) { set_mario_particle_flags(m, PARTICLE_VERTICAL_STAR, FALSE); set_mario_action(m, ACT_BACKWARD_AIR_KB, 0); if (allowCameraChange) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -1927,7 +1927,7 @@ s32 act_flying(struct MarioState *m) { if (m->input & INPUT_Z_PRESSED) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { if (m->playerIndex == 0) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -1941,7 +1941,7 @@ s32 act_flying(struct MarioState *m) { if (!(m->flags & MARIO_WING_CAP)) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { if (m->playerIndex == 0) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -1954,7 +1954,7 @@ s32 act_flying(struct MarioState *m) { if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { if (m->playerIndex == 0) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); // note: EX sets it to the following line instead, but I have // no idea why... possibly copy/paste error? @@ -2007,7 +2007,7 @@ s32 act_flying(struct MarioState *m) { m->faceAngle[0] = 0; if (m->playerIndex == 0) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -2034,7 +2034,7 @@ s32 act_flying(struct MarioState *m) { set_mario_action(m, ACT_BACKWARD_AIR_KB, 0); if (m->playerIndex == 0) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -2126,7 +2126,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { #ifndef VERSION_JP if (m->input & (INPUT_B_PRESSED | INPUT_Z_PRESSED)) { if (m->playerIndex == 0 && m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; @@ -2170,7 +2170,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { if (m->vel[1] < 4.0f) { if (m->playerIndex == 0 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { - if (newcam_active == 0) { + if (!gNewCamera.isActive) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } else { m->area->camera->mode = CAMERA_MODE_NEWCAM; diff --git a/src/pc/controller/controller_sdl1.c b/src/pc/controller/controller_sdl1.c index abb269fcb..cf6f87903 100644 --- a/src/pc/controller/controller_sdl1.c +++ b/src/pc/controller/controller_sdl1.c @@ -24,6 +24,7 @@ #include "../fs/fs.h" #include "game/level_update.h" +#include "game/bettercamera.h" #include "pc/djui/djui.h" @@ -42,8 +43,6 @@ enum { MAX_AXES, }; -extern u8 newcam_mouse; - static bool init_ok; static SDL_Joystick *sdl_joy; @@ -125,7 +124,7 @@ static void controller_sdl_init(void) { joy_axis_binds[i] = -1; } - if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { + if (gNewCamera.isMouse && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { controller_mouse_enter_relative(); } controller_mouse_read_relative(); @@ -153,7 +152,7 @@ extern s16 gMenuMode; static void controller_sdl_read(OSContPad *pad) { if (!init_ok) return; - if (newcam_mouse == 1 && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { + if (gNewCamera.isMouse && gMenuMode == -1 && !gDjuiChatBoxFocus && !gDjuiConsoleFocus) { controller_mouse_enter_relative(); } else { controller_mouse_leave_relative(); diff --git a/src/pc/controller/controller_sdl2.c b/src/pc/controller/controller_sdl2.c index 3dee311fd..373065415 100644 --- a/src/pc/controller/controller_sdl2.c +++ b/src/pc/controller/controller_sdl2.c @@ -23,6 +23,7 @@ #include "game/level_update.h" #include "game/first_person_cam.h" +#include "game/bettercamera.h" #include "pc/lua/utils/smlua_misc_utils.h" #include "pc/djui/djui.h" #include "pc/djui/djui_panel_pause.h" @@ -33,8 +34,6 @@ #define MAX_JOYBUTTONS 32 // arbitrary; includes virtual keys for triggers #define AXIS_THRESHOLD (30 * 256) -extern u8 newcam_mouse; - static bool init_ok = false; static bool haptics_enabled = false; static SDL_GameController *sdl_cntrl = NULL; @@ -134,7 +133,7 @@ static void controller_sdl_init(void) { free(gcdata); } - if (newcam_mouse == 1) { controller_mouse_enter_relative(); } + if (gNewCamera.isMouse) { controller_mouse_enter_relative(); } controller_mouse_read_relative(); controller_sdl_bind(); @@ -181,7 +180,7 @@ extern s16 gMenuMode; static void controller_sdl_read(OSContPad *pad) { if (!init_ok) { return; } - if ((newcam_mouse == 1 || get_first_person_enabled() || gDjuiHudLockMouse) && !is_game_paused() && !gDjuiPanelPauseCreated && !gDjuiInMainMenu && !gDjuiChatBoxFocus && !gDjuiConsoleFocus && WAPI.has_focus()) { + if ((gNewCamera.isMouse || get_first_person_enabled() || gDjuiHudLockMouse) && !is_game_paused() && !gDjuiPanelPauseCreated && !gDjuiInMainMenu && !gDjuiChatBoxFocus && !gDjuiConsoleFocus && WAPI.has_focus()) { controller_mouse_enter_relative(); } else { controller_mouse_leave_relative();