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;
/*????*/ u8 knockbackTimer;
/*????*/ u8 specialTripleJump;
/*????*/ Vec3f wallNormal;
};
struct TextureInfo

View File

@ -2264,4 +2264,26 @@ void set_mario_particle_flags(struct MarioState* m, u32 flags, u8 clear) {
} else {
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_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

View File

@ -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;

View File

@ -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) {

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) {
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;
}