diff --git a/mods/sm74/main.lua b/mods/sm74/main.lua index d47cfaf2..10f9af60 100644 --- a/mods/sm74/main.lua +++ b/mods/sm74/main.lua @@ -26,7 +26,6 @@ gBehaviorValues.dialogs.KoopaQuickBobWinDialog = DIALOG_031 gBehaviorValues.dialogs.KoopaQuickThiWinDialog = DIALOG_031 gLevelValues.fixCollisionBugs = 1 -gLevelValues.fixCollisionBugsRoundedCorners = 0 -------------- -- movtexs -- diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 6bff4a5c..464da2c9 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -15,6 +15,7 @@ Vec3f gFindWallDirection = { 0 }; u8 gFindWallDirectionActive = false; +u8 gFindWallDirectionAirborne = false; #define CLAMP(_val, _min, _max) MAX(MIN((_val), _max), _min) @@ -134,7 +135,7 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, continue; } - if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners) { + if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners && !gFindWallDirectionAirborne) { // Check AABB to exclude walls before doing expensive triangle check f32 minX = MIN(MIN(surf->vertex1[0], surf->vertex2[0]), surf->vertex3[0]) - radius; f32 minZ = MIN(MIN(surf->vertex1[2], surf->vertex2[2]), surf->vertex3[2]) - radius; @@ -277,7 +278,7 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, //! (Wall Overlaps) Because this doesn't update the x and z local variables, // multiple walls can push mario more than is required. // - if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners) { + if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners && !gFindWallDirectionAirborne) { data->x = cPos[0] + cNorm[0] * radius; data->z = cPos[2] + cNorm[2] * radius; x = data->x; diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index 84ae7964..4f58f659 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -40,6 +40,7 @@ struct FloorGeometry extern Vec3f gFindWallDirection; extern u8 gFindWallDirectionActive; +extern u8 gFindWallDirectionAirborne; s32 f32_find_wall_collision(f32 *xPtr, f32 *yPtr, f32 *zPtr, f32 offsetY, f32 radius); s32 find_wall_collisions(struct WallCollisionData *colData); diff --git a/src/game/mario.c b/src/game/mario.c index 6151e8bb..eb37c8e8 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2385,9 +2385,32 @@ void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) { void mario_update_wall(struct MarioState* m, struct WallCollisionData* wcd) { if (!m || !wcd) { return; } - m->wall = (wcd->numWalls > 0) - ? wcd->walls[wcd->numWalls - 1] - : NULL; + if (gLevelValues.fixCollisionBugs) { + // turn face angle into a direction vector + Vec3f faceAngle; + faceAngle[0] = coss(m->faceAngle[0]) * sins(m->faceAngle[1]); + faceAngle[1] = sins(m->faceAngle[0]); + faceAngle[2] = coss(m->faceAngle[0]) * coss(m->faceAngle[1]); + vec3f_normalize(faceAngle); + + // reset wall + m->wall = NULL; + for (int i = 0; i < wcd->numWalls; i++) { + if (m->wall == NULL) { + m->wall = wcd->walls[i]; + continue; + } + + // find the wall that is most "facing away" + if (vec3f_dist((f32*)&m->wall->normal.x, (f32*)faceAngle) < vec3f_dist((f32*)&wcd->walls[i]->normal.x, (f32*)faceAngle)) { + m->wall = wcd->walls[i]; + } + } + } else { + m->wall = (wcd->numWalls > 0) + ? wcd->walls[wcd->numWalls - 1] + : NULL; + } if (gLevelValues.fixCollisionBugs && wcd->normalCount > 0) { vec3f_set(m->wallNormal, diff --git a/src/game/mario_step.c b/src/game/mario_step.c index be79e350..2866eddb 100644 --- a/src/game/mario_step.c +++ b/src/game/mario_step.c @@ -741,7 +741,9 @@ s32 perform_air_step(struct MarioState *m, u32 stepArg) { vec3f_copy(gFindWallDirection, step); gFindWallDirectionActive = true; + gFindWallDirectionAirborne = true; quarterStepResult = perform_air_quarter_step(m, intendedPos, stepArg); + gFindWallDirectionAirborne = false; gFindWallDirectionActive = false; //! On one qf, hit OOB/ceil/wall to store the 2 return value, and continue