diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index f8df67586..a61f7b0d4 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -1985,6 +1985,9 @@ CAMERA_MODE_PARALLEL_TRACKING = 0x0C --- @type integer CAMERA_MODE_RADIAL = 0x01 +--- @type integer +CAMERA_MODE_ROM_HACK = 0x13 + --- @type integer CAMERA_MODE_SLIDE_HOOT = 0x09 diff --git a/docs/lua/constants.md b/docs/lua/constants.md index b3e7f786e..9baaf575c 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -611,6 +611,7 @@ - CAMERA_MODE_OUTWARD_RADIAL - CAMERA_MODE_PARALLEL_TRACKING - CAMERA_MODE_RADIAL +- CAMERA_MODE_ROM_HACK - CAMERA_MODE_SLIDE_HOOT - CAMERA_MODE_SPIRAL_STAIRS - CAMERA_MODE_WATER_SURFACE diff --git a/src/game/camera.c b/src/game/camera.c index db3d0d940..d4236be08 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -461,6 +461,8 @@ s32 update_fixed_camera(struct Camera *c, Vec3f, Vec3f); s32 update_8_directions_camera(struct Camera *c, Vec3f, Vec3f); s32 update_slide_or_0f_camera(struct Camera *c, Vec3f, Vec3f); s32 update_spiral_stairs_camera(struct Camera *c, Vec3f, Vec3f); +s32 update_rom_hack_camera(struct Camera *c, Vec3f, Vec3f); +void mode_rom_hack_camera(struct Camera *c); typedef s32 (*CameraTransition)(struct Camera *c, Vec3f, Vec3f); CameraTransition sModeTransitions[] = { @@ -481,7 +483,9 @@ CameraTransition sModeTransitions[] = { update_8_directions_camera, update_slide_or_0f_camera, update_mario_camera, - update_spiral_stairs_camera + update_spiral_stairs_camera, + NULL, + update_rom_hack_camera, }; // Move these two tables to another include file? @@ -3206,6 +3210,10 @@ void update_camera(struct Camera *c) { mode_spiral_stairs_camera(c); break; + case CAMERA_MODE_ROM_HACK: + mode_rom_hack_camera(c); + break; + #ifdef BETTERCAMERA case CAMERA_MODE_NEWCAM: newcam_loop(c); @@ -3455,7 +3463,7 @@ void init_camera(struct Camera *c) { vec3f_set(sFixedModeBasePosition, -2985.f, 478.f, -5568.f); break; } - if (c->mode == CAMERA_MODE_8_DIRECTIONS) { + if ((c->mode == CAMERA_MODE_8_DIRECTIONS) || c->mode == CAMERA_MODE_ROM_HACK) { gCameraMovementFlags |= CAM_MOVE_ZOOMED_OUT; } switch (gCurrLevelArea) { @@ -11711,3 +11719,265 @@ void camera_set_use_course_specific_settings(u8 enable) { #include "behaviors/end_birds_1.inc.c" #include "behaviors/end_birds_2.inc.c" #include "behaviors/intro_scene.inc.c" + +/////////////////////// + +static s16 sRomHackYaw = 0; +static u8 sRomHackZoom = 1; +static s8 sRomHackIsUpdate = 0; + +static void vec3f_project(Vec3f vec, Vec3f onto, Vec3f out) { + f32 numerator = vec3f_dot(vec, onto); + f32 denominator = vec3f_dot(onto, onto); + if (denominator == 0) { + out[0] = 0; + out[1] = 0; + out[2] = 0; + return; + } + vec3f_copy(out, onto); + vec3f_mul(out, numerator / denominator); +} + +static f32 vec3f_dist(Vec3f v1, Vec3f v2) { + Vec3f diff = { + v1[0] - v2[0], + v1[1] - v2[1], + v1[2] - v2[2], + }; + return vec3f_length(diff); +} + +static u8 rom_hack_cam_can_see_mario(Vec3f desiredPos) { + // do collision checking + struct Surface *surf = NULL; + f32 floorHeight = find_floor(desiredPos[0], desiredPos[1], desiredPos[2], &surf); + if (surf == NULL || floorHeight <= -11000) { + return false; + } + + f32 mDist; + s16 mPitch; + s16 mYaw; + vec3f_get_dist_and_angle(desiredPos, gMarioStates[0].pos, &mDist, &mPitch, &mYaw); + + s16 degreeMult = sRomHackZoom ? 7 : 5; + + for (s16 yawOffset = -1; yawOffset <= 1; yawOffset++) { + for (s16 pitchOffset = -1; pitchOffset <= 1; pitchOffset++) { + if (abs(yawOffset) == 1 && abs(pitchOffset) == 1) { continue; } + Vec3f target; + vec3f_set_dist_and_angle(desiredPos, + target, + mDist, + mPitch + DEGREES(pitchOffset) * degreeMult, + mYaw + DEGREES(yawOffset) * degreeMult); + + target[1] += 75; + + Vec3f camdir; + camdir[0] = target[0] - desiredPos[0]; + camdir[1] = target[1] - desiredPos[1]; + camdir[2] = target[2] - desiredPos[2]; + + Vec3f hitpos; + find_surface_on_ray(desiredPos, camdir, &surf, hitpos); + if (surf == NULL) { + return true; + } + } + } + + return false; +} + +void rom_hack_cam_walk(Vec3f pos, Vec3f dir, f32 dist) { + Vec3f movement = { + dir[0] * dist, + dir[1] * dist, + dir[2] * dist, + }; + + struct Surface* surf = NULL; + Vec3f hitpos; + find_surface_on_ray(pos, movement, &surf, hitpos); + if (surf == NULL) { + pos[0] += movement[0]; + pos[1] += movement[1]; + pos[2] += movement[2]; + return; + } + + Vec3f prevPos = { + pos[0], + pos[1], + pos[2], + }; + + // figure out dir normal + Vec3f dirNorm; + vec3f_copy(dirNorm, dir); + vec3f_normalize(dirNorm); + + // figure out parallel direction + Vec3f normal = { + surf->normal.x, + surf->normal.y, + surf->normal.z, + }; + vec3f_project(dirNorm, normal, dir); + dir[0] = dirNorm[0] - dir[0]; + dir[1] = dirNorm[1] - dir[1]; + dir[2] = dirNorm[2] - dir[2]; + vec3f_normalize(dir); + + // move pos off of hitpos + pos[0] = hitpos[0]; + pos[1] = hitpos[1]; + pos[2] = hitpos[2]; + vec3f_mul(dirNorm, 100); + vec3f_sub(pos, dirNorm); + + // figure out remaining length + f32 moveDist = vec3f_dist(prevPos, pos); + dist = dist * 0.7 - moveDist; + if (dist > 10 && vec3f_length(dir) > 0 && moveDist > 1) { + rom_hack_cam_walk(pos, dir, dist); + } +} + +/** + * A mode that has 8 camera angles, 45 degrees apart, that is slightly smarter + */ +void mode_rom_hack_camera(struct Camera *c) { + s16 oldAreaYaw = sAreaYaw; + + // look left + if (gMarioStates[0].controller->buttonPressed & L_CBUTTONS) { + sRomHackYaw += DEGREES(45); + play_sound_cbutton_side(); + } + + // look right + if (gMarioStates[0].controller->buttonPressed & R_CBUTTONS) { + sRomHackYaw -= DEGREES(45); + play_sound_cbutton_side(); + } + + // zoom in + if ((gMarioStates[0].controller->buttonPressed & U_CBUTTONS)) { + if (!sRomHackZoom) { + sRomHackZoom = 1; + play_sound_cbutton_up(); + } else { + set_mode_c_up(c); + } + } + + // zoom out + if ((gMarioStates[0].controller->buttonPressed & D_CBUTTONS)) { + if (sRomHackZoom) { + play_sound_cbutton_down(); + } else { + play_sound_button_change_blocked(); + } + sRomHackZoom = 0; + } + + // center camera + if (gMarioStates[0].controller->buttonPressed & L_TRIG) { + sRomHackYaw = DEGREES(180 + 90) - gMarioStates[0].intendedYaw; + sRomHackYaw = (sRomHackYaw / DEGREES(45)) * DEGREES(45); + } + + // clamp yaw + sRomHackYaw = (sRomHackYaw / DEGREES(45)) * DEGREES(45); + + // update the camera focus and such + Vec3f pos; + sRomHackIsUpdate = 1; + update_rom_hack_camera(c, c->focus, pos); + sRomHackIsUpdate = 0; + + // figure out desired position + f32 desiredDist = sRomHackZoom ? 900 : 1400; + f32 desiredHeight = sRomHackZoom ? 350 : 500; + f32* mPos = &gMarioStates[0].pos[0]; + pos[0] = mPos[0] + coss(sRomHackYaw) * desiredDist; + pos[1] = mPos[1] + desiredHeight; + pos[2] = mPos[2] + sins(sRomHackYaw) * desiredDist; + + if (rom_hack_cam_can_see_mario(pos)) { + // we can see mario, no need to adjust + c->pos[0] = pos[0]; + c->pos[1] = pos[1]; + c->pos[2] = pos[2]; + } else { + // we can't see mario, raycast a position + Vec3f dir; + dir[0] = pos[0] - mPos[0]; + dir[1] = pos[1] - mPos[1]; + dir[2] = pos[2] - mPos[2]; + vec3f_normalize(dir); + + // start at mario + c->pos[0] = gMarioStates[0].pos[0]; + c->pos[1] = gMarioStates[0].pos[1] + 50; + c->pos[2] = gMarioStates[0].pos[2]; + + rom_hack_cam_walk(c->pos, dir, desiredDist); + } + + + // tween + c->pos[0] = c->pos[0] * 0.2 + oldPos[0] * 0.8; + c->pos[1] = c->pos[1] * 0.2 + oldPos[1] * 0.8; + c->pos[2] = c->pos[2] * 0.2 + oldPos[2] * 0.8; + set_camera_height(c, c->pos[1]); + + // update HUD + if (sRomHackZoom) { + gCameraMovementFlags &= ~(CAM_MOVE_ZOOMED_OUT); + } else { + gCameraMovementFlags |= (CAM_MOVE_ZOOMED_OUT); + } + + // update camera yaw + c->yaw = atan2s( + c->pos[2] - gMarioStates[0].pos[2], + c->pos[0] - gMarioStates[0].pos[0]); + + // update area yaw + sAreaYaw = sRomHackYaw; + sAreaYawChange = sAreaYaw - oldAreaYaw; +} + +s32 update_rom_hack_camera(struct Camera *c, Vec3f focus, Vec3f pos) { + UNUSED f32 cenDistX = sMarioCamState->pos[0] - c->areaCenX; + UNUSED f32 cenDistZ = sMarioCamState->pos[2] - c->areaCenZ; + + // if rom hack camera was just set, figure out the yaw to use + if (!sRomHackIsUpdate) { + sRomHackYaw = DEGREES(90) - atan2s( + c->pos[2] - gMarioStates[0].pos[2], + c->pos[0] - gMarioStates[0].pos[0]); + } + + s16 camYaw = c->yaw; + s16 pitch = look_down_slopes(camYaw); + f32 posY; + f32 focusY; + f32 yOff = 125.f; + f32 baseDist = 1000; + + 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, sAreaYaw); + pan_ahead_of_player(c); + if (gCameraUseCourseSpecificSettings && gCurrLevelArea == AREA_DDD_SUB) { + camYaw = clamp_positions_and_find_yaw(pos, focus, 6839.f, 995.f, 5994.f, -3945.f); + } + + c->yaw = DEGREES(90) - sRomHackYaw; + return camYaw; +} diff --git a/src/game/camera.h b/src/game/camera.h index 257207894..c2d3bb8ae 100644 --- a/src/game/camera.h +++ b/src/game/camera.h @@ -115,6 +115,7 @@ #ifdef BETTERCAMERA #define CAMERA_MODE_NEWCAM 0x12 #endif +#define CAMERA_MODE_ROM_HACK 0x13 #define CAM_MOVE_RETURN_TO_MIDDLE 0x0001 #define CAM_MOVE_ZOOMED_OUT 0x0002 diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index ec432aa90..7dda1efa4 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -49,6 +49,30 @@ static void debug_warp_level2() { dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1); } +#include "src/game/camera.h" +static void debug_warp_level3() { + //dynos_warp_to_level(gCurrLevelNum, gCurrAreaIndex^3, 1); + u8 cameraModes[] = { + CAMERA_MODE_NONE, + CAMERA_MODE_RADIAL, + CAMERA_MODE_OUTWARD_RADIAL, + CAMERA_MODE_BEHIND_MARIO, + CAMERA_MODE_CLOSE, + CAMERA_MODE_WATER_SURFACE, + CAMERA_MODE_SLIDE_HOOT, + CAMERA_MODE_INSIDE_CANNON, + CAMERA_MODE_BOSS_FIGHT, + CAMERA_MODE_FIXED, + CAMERA_MODE_8_DIRECTIONS, + CAMERA_MODE_FREE_ROAM, + CAMERA_MODE_SPIRAL_STAIRS, + }; + static int index = 0; + index = (index + 1)%15; + printf(">>> %u\n", index); + set_camera_mode(gCamera, cameraModes[index], 0); +} + static void debug_grand_star(void) { set_mario_action(&gMarioStates[0], ACT_JUMBO_STAR_CUTSCENE, 0); } @@ -90,6 +114,7 @@ void debug_keyboard_on_key_down(int scancode) { #ifdef DEVELOPMENT case SCANCODE_1: if (sHoldingAlt) { debug_warp_level1(); } break; case SCANCODE_2: if (sHoldingAlt) { debug_warp_level2(); } break; + case SCANCODE_4: if (sHoldingAlt) { debug_warp_level3(); } break; case SCANCODE_8: if (sHoldingAlt) { debug_spawn_object(); } break; case SCANCODE_9: if (sHoldingAlt) { debug_warp_to(); } break; case SCANCODE_0: if (sHoldingAlt) { debug_suicide(); } break; diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 74f5b125b..ffe48425a 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -866,6 +866,7 @@ char gSmluaConstants[] = "" "CAMERA_MODE_FREE_ROAM = 0x10\n" "CAMERA_MODE_SPIRAL_STAIRS = 0x11\n" "CAMERA_MODE_NEWCAM = 0x12\n" +"CAMERA_MODE_ROM_HACK = 0x13\n" "CAM_MOVE_RETURN_TO_MIDDLE = 0x0001\n" "CAM_MOVE_ZOOMED_OUT = 0x0002\n" "CAM_MOVE_ROTATE_RIGHT = 0x0004\n"