Adjust wall normal when colliding with multiple walls

This commit is contained in:
MysterD 2022-05-31 18:26:27 -07:00
parent bd7974a544
commit 3e46cc1161
6 changed files with 42 additions and 16 deletions

View file

@ -387,6 +387,7 @@ struct MarioState
/*????*/ f32 curAnimOffset; /*????*/ f32 curAnimOffset;
/*????*/ u8 knockbackTimer; /*????*/ u8 knockbackTimer;
/*????*/ u8 specialTripleJump; /*????*/ u8 specialTripleJump;
/*????*/ Vec3f wallNormal;
}; };
struct TextureInfo struct TextureInfo

View file

@ -2265,3 +2265,25 @@ void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) {
m->particleFlags |= flags; m->particleFlags |= flags;
} }
} }
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);
}
}

View file

@ -60,5 +60,6 @@ void init_single_mario(struct MarioState* m);
void init_mario(void); void init_mario(void);
void init_mario_from_save_file(void); void init_mario_from_save_file(void);
void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear); 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 #endif // MARIO_H

View file

@ -52,7 +52,7 @@ void play_knockback_sound(struct MarioState *m) {
#endif #endif
s32 lava_boost_on_wall(struct MarioState *m) { 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) { if (m->forwardVel < 24.0f) {
m->forwardVel = 24.0f; m->forwardVel = 24.0f;

View file

@ -695,7 +695,7 @@ void push_or_sidle_wall(struct MarioState *m, Vec3f startPos) {
} }
if (m->wall != NULL) { 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]; dWallAngle = wallAngle - m->faceAngle[1];
} }
@ -1407,7 +1407,7 @@ void common_slide_action(struct MarioState *m, u32 endAction, u32 airAction, s32
#endif #endif
slide_bonk(m, ACT_GROUND_BONK, endAction); slide_bonk(m, ACT_GROUND_BONK, endAction);
} else if (m->wall != NULL) { } 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); f32 slideSpeed = sqrtf(m->slideVelX * m->slideVelX + m->slideVelZ * m->slideVelZ);
if ((slideSpeed *= 0.9) < 4.0f) { if ((slideSpeed *= 0.9) < 4.0f) {

View file

@ -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) { void mario_bonk_reflection(struct MarioState *m, u32 negateSpeed) {
if (m->wall != NULL) { 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); m->faceAngle[1] = wallAngle - (s16)(m->faceAngle[1] - wallAngle);
play_sound((m->flags & MARIO_METAL_CAP) ? SOUND_ACTION_METAL_BONK : SOUND_ACTION_BONK, 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]); waterLevel = find_water_level(nextPos[0], nextPos[2]);
m->wall = (upperWcd.numWalls > 0) mario_update_wall(m, &upperWcd);
? upperWcd.walls[upperWcd.numWalls - 1]
: NULL;
if (floor == NULL) { if (floor == NULL) {
return GROUND_STEP_HIT_WALL_STOP_QSTEPS; 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; m->floorHeight = floorHeight;
if (upperWcd.numWalls > 0) { if (upperWcd.numWalls > 0) {
mario_update_wall(m, &upperWcd);
for (u8 i = 0; i < upperWcd.numWalls; i++) { for (u8 i = 0; i < upperWcd.numWalls; i++) {
if (!gServerSettings.fixCollisionBugs) { if (!gServerSettings.fixCollisionBugs) {
i = (upperWcd.numWalls - 1); i = (upperWcd.numWalls - 1);
} }
struct Surface* wall = upperWcd.walls[i]; 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 (wall->type == SURFACE_BURNING) {
m->wall = wall;
if (m->wall->type == SURFACE_BURNING) {
return AIR_STEP_HIT_LAVA_WALL; return AIR_STEP_HIT_LAVA_WALL;
} }
if (wallDYaw < -0x6000 || wallDYaw > 0x6000) { if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
m->wall = wall;
m->flags |= MARIO_UNKNOWN_30; m->flags |= MARIO_UNKNOWN_30;
return AIR_STEP_HIT_WALL; return AIR_STEP_HIT_WALL;
} }
} }
} else if (lowerWcd.numWalls > 0) { } else if (lowerWcd.numWalls > 0) {
mario_update_wall(m, &lowerWcd);
for (u8 i = 0; i < lowerWcd.numWalls; i++) { for (u8 i = 0; i < lowerWcd.numWalls; i++) {
if (!gServerSettings.fixCollisionBugs) { if (!gServerSettings.fixCollisionBugs) {
i = (lowerWcd.numWalls - 1); i = (lowerWcd.numWalls - 1);
} }
struct Surface* wall = lowerWcd.walls[i]; 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 (wall->type == SURFACE_BURNING) {
m->wall = wall;
if (m->wall->type == SURFACE_BURNING) {
return AIR_STEP_HIT_LAVA_WALL; return AIR_STEP_HIT_LAVA_WALL;
} }
if (wallDYaw < -0x6000 || wallDYaw > 0x6000) { if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
m->wall = wall;
m->flags |= MARIO_UNKNOWN_30; m->flags |= MARIO_UNKNOWN_30;
return AIR_STEP_HIT_WALL; return AIR_STEP_HIT_WALL;
} }