From 3e46cc11619c0f8ee80e8876c73150521e771e11 Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 31 May 2022 18:26:27 -0700 Subject: [PATCH] Adjust wall normal when colliding with multiple walls --- include/types.h | 1 + src/game/mario.c | 24 +++++++++++++++++++++++- src/game/mario.h | 1 + src/game/mario_actions_airborne.c | 2 +- src/game/mario_actions_moving.c | 4 ++-- src/game/mario_step.c | 26 ++++++++++++++------------ 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/include/types.h b/include/types.h index 57049fbf..c3f67223 100644 --- a/include/types.h +++ b/include/types.h @@ -387,6 +387,7 @@ struct MarioState /*????*/ f32 curAnimOffset; /*????*/ u8 knockbackTimer; /*????*/ u8 specialTripleJump; + /*????*/ Vec3f wallNormal; }; struct TextureInfo diff --git a/src/game/mario.c b/src/game/mario.c index 3b8df2b8..8a5a89a9 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -2264,4 +2264,26 @@ void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) { } else { m->particleFlags |= flags; } -} \ No newline at end of file +} + +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; + + vec3f_set(m->wallNormal, 0, 0, 0); + for (u8 i = 0; i < wcd->numWalls; i++) { + if (!gServerSettings.fixCollisionBugs) { + i = (wcd->numWalls - 1); + } + struct Surface* wall = wcd->walls[i]; + Vec3f normal = { wall->normal.x, wall->normal.y, wall->normal.z }; + vec3f_add(m->wallNormal, normal); + } + + if (m->wall) { + vec3f_normalize(m->wallNormal); + } +} diff --git a/src/game/mario.h b/src/game/mario.h index d4573745..de1f5490 100644 --- a/src/game/mario.h +++ b/src/game/mario.h @@ -60,5 +60,6 @@ void init_single_mario(struct MarioState* m); void init_mario(void); void init_mario_from_save_file(void); void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear); +void mario_update_wall(struct MarioState* m, struct WallCollisionData* wcd); #endif // MARIO_H diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index 9a4c8fc2..63a4fd56 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -52,7 +52,7 @@ void play_knockback_sound(struct MarioState *m) { #endif s32 lava_boost_on_wall(struct MarioState *m) { - m->faceAngle[1] = atan2s(m->wall->normal.z, m->wall->normal.x); + m->faceAngle[1] = atan2s(m->wallNormal[2], m->wallNormal[0]); if (m->forwardVel < 24.0f) { m->forwardVel = 24.0f; diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index 032ef80d..487d6a62 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -695,7 +695,7 @@ void push_or_sidle_wall(struct MarioState *m, Vec3f startPos) { } if (m->wall != NULL) { - wallAngle = atan2s(m->wall->normal.z, m->wall->normal.x); + wallAngle = atan2s(m->wallNormal[2], m->wallNormal[0]); dWallAngle = wallAngle - m->faceAngle[1]; } @@ -1407,7 +1407,7 @@ void common_slide_action(struct MarioState *m, u32 endAction, u32 airAction, s32 #endif slide_bonk(m, ACT_GROUND_BONK, endAction); } else if (m->wall != NULL) { - s16 wallAngle = atan2s(m->wall->normal.z, m->wall->normal.x); + s16 wallAngle = atan2s(m->wallNormal[2], m->wallNormal[0]); f32 slideSpeed = sqrtf(m->slideVelX * m->slideVelX + m->slideVelZ * m->slideVelZ); if ((slideSpeed *= 0.9) < 4.0f) { diff --git a/src/game/mario_step.c b/src/game/mario_step.c index 583eab0d..d45e410e 100644 --- a/src/game/mario_step.c +++ b/src/game/mario_step.c @@ -90,7 +90,7 @@ BAD_RETURN(s32) init_bully_collision_data(struct BullyCollisionData *data, f32 p void mario_bonk_reflection(struct MarioState *m, u32 negateSpeed) { if (m->wall != NULL) { - s16 wallAngle = atan2s(m->wall->normal.z, m->wall->normal.x); + s16 wallAngle = atan2s(m->wallNormal[2], m->wallNormal[0]); m->faceAngle[1] = wallAngle - (s16)(m->faceAngle[1] - wallAngle); play_sound((m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_BONK : SOUND_ACTION_BONK, @@ -274,9 +274,7 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) { waterLevel = find_water_level(nextPos[0], nextPos[2]); - m->wall = (upperWcd.numWalls > 0) - ? upperWcd.walls[upperWcd.numWalls - 1] - : NULL; + mario_update_wall(m, &upperWcd); if (floor == NULL) { return GROUND_STEP_HIT_WALL_STOP_QSTEPS; @@ -501,41 +499,45 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr m->floorHeight = floorHeight; if (upperWcd.numWalls > 0) { + mario_update_wall(m, &upperWcd); + for (u8 i = 0; i < upperWcd.numWalls; i++) { if (!gServerSettings.fixCollisionBugs) { i = (upperWcd.numWalls - 1); } struct Surface* wall = upperWcd.walls[i]; - m->wall = wall; + wallDYaw = atan2s(wall->normal.z, wall->normal.x) - m->faceAngle[1]; - wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1]; - - if (m->wall->type == SURFACE_BURNING) { + if (wall->type == SURFACE_BURNING) { + m->wall = wall; return AIR_STEP_HIT_LAVA_WALL; } if (wallDYaw < -0x6000 || wallDYaw > 0x6000) { + m->wall = wall; m->flags |= MARIO_UNKNOWN_30; return AIR_STEP_HIT_WALL; } } } else if (lowerWcd.numWalls > 0) { + mario_update_wall(m, &lowerWcd); + for (u8 i = 0; i < lowerWcd.numWalls; i++) { if (!gServerSettings.fixCollisionBugs) { i = (lowerWcd.numWalls - 1); } struct Surface* wall = lowerWcd.walls[i]; - m->wall = wall; + wallDYaw = atan2s(wall->normal.z, wall->normal.x) - m->faceAngle[1]; - wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1]; - - if (m->wall->type == SURFACE_BURNING) { + if (wall->type == SURFACE_BURNING) { + m->wall = wall; return AIR_STEP_HIT_LAVA_WALL; } if (wallDYaw < -0x6000 || wallDYaw > 0x6000) { + m->wall = wall; m->flags |= MARIO_UNKNOWN_30; return AIR_STEP_HIT_WALL; }