From f88aee251ecb2e7db92951da292c548937303d14 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 18 Oct 2020 11:57:45 -0700 Subject: [PATCH] Keep BETTERCAM/bubbled players within the minimum Y bounds of levels Players/cameras were able to clip inside of island-like levels previously. I have hardcoded sane minimum Y values for the following courses: WF, CCM, PSS, BITDW, TTM, RR, BITS --- src/game/area.c | 12 ++++++++++++ src/game/area.h | 2 ++ src/game/bettercamera.inc.h | 9 +++++++++ src/game/mario_actions_automatic.c | 9 +++++++++ 4 files changed, 32 insertions(+) diff --git a/src/game/area.c b/src/game/area.c index dff969551..aff256358 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -456,3 +456,15 @@ void render_game(void) { D_8032CE74 = NULL; D_8032CE78 = 0; } + +void get_area_minimum_y(u8* hasMinY, f32* minY) { + switch (gCurrCourseNum) { + case COURSE_WF: *hasMinY = TRUE; *minY = 8; break; + case COURSE_CCM: *hasMinY = TRUE; *minY = (gCurrAreaIndex == 2) ? -5856 : -5068; break; + case COURSE_PSS: *hasMinY = TRUE; *minY = -4600; break; + case COURSE_BITDW: *hasMinY = TRUE; *minY = -3416; break; + case COURSE_TTM: *hasMinY = (gCurrAreaIndex == 1) ? TRUE : FALSE; *minY = -6000; break; + case COURSE_RR: *hasMinY = TRUE; *minY = -4790; break; + case COURSE_BITS: *hasMinY = TRUE; *minY = -5065; break; + } +} diff --git a/src/game/area.h b/src/game/area.h index be0369653..90c612612 100644 --- a/src/game/area.h +++ b/src/game/area.h @@ -163,4 +163,6 @@ void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue); void play_transition_after_delay(s16 transType, s16 time, u8 red, u8 green, u8 blue, s16 delay); void render_game(void); +void get_area_minimum_y(u8* hasMinY, f32* minY); + #endif // AREA_H diff --git a/src/game/bettercamera.inc.h b/src/game/bettercamera.inc.h index f428eeac3..3d048e18c 100644 --- a/src/game/bettercamera.inc.h +++ b/src/game/bettercamera.inc.h @@ -562,6 +562,14 @@ static void newcam_set_pan(void) { newcam_pan_z = newcam_pan_z*(min(newcam_distance/newcam_distance_target,1)); } +static void newcam_level_bounds() { + u8 hasMinY = FALSE; + f32 minY = 0; + get_area_minimum_y(&hasMinY, &minY); + if (!hasMinY) { return; } + newcam_pos[1] = MAX(newcam_pos[1], minY); +} + static void newcam_position_cam(void) { f32 floorY = 0; f32 floorY2 = 0; @@ -595,6 +603,7 @@ static void newcam_position_cam(void) { if (newcam_modeflags & NC_FLAG_FOCUSZ) newcam_lookat[2] = newcam_pos_target[2]-newcam_pan_z; + newcam_level_bounds(); if (newcam_modeflags & NC_FLAG_COLLISION) { newcam_collision(); newcam_bounding_box(); diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index f069a761b..7b02b8120 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -969,6 +969,15 @@ s32 act_bubbled(struct MarioState* m) { m->vel[i] = (oldVel[i] * 0.9f + m->vel[i] * 0.1f); } + // enforce minimum y for the level + u8 hasMinY = FALSE; + f32 minY = 0; + get_area_minimum_y(&hasMinY, &minY); + if (hasMinY && m->pos[1] < minY) { + m->vel[1] = MAX(0, m->vel[1]); + m->pos[1] += 25; + } + // move player switch (perform_air_step(m, 0)) { case AIR_STEP_LANDED: