Merge pull request #2 from Cheezepin/master

Frame's patch (rounded corners and quarter-step shenanigans)
This commit is contained in:
Reonu
2021-05-06 22:10:29 +01:00
committed by GitHub
4 changed files with 387 additions and 114 deletions

View File

@@ -18,6 +18,8 @@
*/
static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
struct WallCollisionData *data) {
const f32 corner_threshold = -0.9f;
register struct Surface *surf;
register f32 offset;
register f32 radius = data->radius;
@@ -27,6 +29,13 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
register f32 px, pz;
register f32 w1, w2, w3;
register f32 y1, y2, y3;
register f32 v0x, v0y, v0z;
register f32 v1x, v1y, v1z;
register f32 v2x, v2y, v2z;
register f32 d00, d01, d11, d20, d21;
register f32 invDenom;
register f32 v, w;
register f32 margin_radius = radius - 1.0f;
s32 numCols = 0;
// Max collision radius = 200
@@ -46,67 +55,67 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
offset = surf->normal.x * x + surf->normal.y * y + surf->normal.z * z + surf->originOffset;
if (offset < -radius || offset > radius) {
if (offset < /*-radius*/ 0 || offset > radius) {
continue;
}
px = x;
pz = z;
// px = x;
// pz = z;
//! (Quantum Tunneling) Due to issues with the vertices walls choose and
// the fact they are floating point, certain floating point positions
// along the seam of two walls may collide with neither wall or both walls.
if (surf->flags & SURFACE_FLAG_X_PROJECTION) {
w1 = -surf->vertex1[2]; w2 = -surf->vertex2[2]; w3 = -surf->vertex3[2];
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
// //! (Quantum Tunneling) Due to issues with the vertices walls choose and
// // the fact they are floating point, certain floating point positions
// // along the seam of two walls may collide with neither wall or both walls.
// if (surf->flags & SURFACE_FLAG_X_PROJECTION) {
// w1 = -surf->vertex1[2]; w2 = -surf->vertex2[2]; w3 = -surf->vertex3[2];
// y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
if (surf->normal.x > 0.0f) {
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) > 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) > 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) > 0.0f) {
continue;
}
} else {
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) < 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) < 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) < 0.0f) {
continue;
}
}
} else {
w1 = surf->vertex1[0]; w2 = surf->vertex2[0]; w3 = surf->vertex3[0];
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
// if (surf->normal.x > 0.0f) {
// if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) > 0.0f) {
// continue;
// }
// if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) > 0.0f) {
// continue;
// }
// if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) > 0.0f) {
// continue;
// }
// } else {
// if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) < 0.0f) {
// continue;
// }
// if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) < 0.0f) {
// continue;
// }
// if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) < 0.0f) {
// continue;
// }
// }
// } else {
// w1 = surf->vertex1[0]; w2 = surf->vertex2[0]; w3 = surf->vertex3[0];
// y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
if (surf->normal.z > 0.0f) {
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) > 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) > 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) > 0.0f) {
continue;
}
} else {
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) < 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) < 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) < 0.0f) {
continue;
}
}
}
// if (surf->normal.z > 0.0f) {
// if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) > 0.0f) {
// continue;
// }
// if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) > 0.0f) {
// continue;
// }
// if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) > 0.0f) {
// continue;
// }
// } else {
// if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) < 0.0f) {
// continue;
// }
// if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) < 0.0f) {
// continue;
// }
// if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) < 0.0f) {
// continue;
// }
// }
// }
// Determine if checking for the camera or not.
if (gCheckingSurfaceCollisionsForCamera) {
@@ -137,9 +146,121 @@ 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.
data->x += surf->normal.x * (radius - offset);
data->z += surf->normal.z * (radius - offset);
// data->x += surf->normal.x * (radius - offset);
// data->z += surf->normal.z * (radius - offset);
v0x = (f32)(surf->vertex2[0] - surf->vertex1[0]);
v0y = (f32)(surf->vertex2[1] - surf->vertex1[1]);
v0z = (f32)(surf->vertex2[2] - surf->vertex1[2]);
v1x = (f32)(surf->vertex3[0] - surf->vertex1[0]);
v1y = (f32)(surf->vertex3[1] - surf->vertex1[1]);
v1z = (f32)(surf->vertex3[2] - surf->vertex1[2]);
v2x = x - (f32)surf->vertex1[0];
v2y = y - (f32)surf->vertex1[1];
v2z = z - (f32)surf->vertex1[2];
//Face
d00 = v0x * v0x + v0y * v0y + v0z * v0z;
d01 = v0x * v1x + v0y * v1y + v0z * v1z;
d11 = v1x * v1x + v1y * v1y + v1z * v1z;
d20 = v2x * v0x + v2y * v0y + v2z * v0z;
d21 = v2x * v1x + v2y * v1y + v2z * v1z;
invDenom = 1.0f / (d00 * d11 - d01 * d01);
v = (d11 * d20 - d01 * d21) * invDenom;
if (v < 0.0f || v > 1.0f)
goto edge_1_2;
w = (d00 * d21 - d01 * d20) * invDenom;
if (w < 0.0f || w > 1.0f || v + w > 1.0f)
goto edge_1_2;
x += surf->normal.x * (radius - offset);
z += surf->normal.z * (radius - offset);
goto hasCollision;
edge_1_2:
if (offset < 0)
continue;
//Edge 1-2
if (v0y != 0.0f) {
v = (v2y / v0y);
if (v < 0.0f || v > 1.0f)
goto edge_1_3;
d00 = v0x * v - v2x;
d01 = v0z * v - v2z;
invDenom = sqrtf(d00 * d00 + d01 * d01);
offset = invDenom - margin_radius;
if (offset > 0.0f)
goto edge_1_3;
invDenom = offset / invDenom;
x += (d00 *= invDenom);
z += (d01 *= invDenom);
margin_radius += 0.01f;
if (d00 * surf->normal.x + d01 * surf->normal.z < corner_threshold * offset)
continue;
else
goto hasCollision;
}
edge_1_3:
//Edge 1-3
if (v1y != 0.0f) {
v = (v2y / v1y);
if (v < 0.0f || v > 1.0f)
goto edge_2_3;
d00 = v1x * v - v2x;
d01 = v1z * v - v2z;
invDenom = sqrtf(d00 * d00 + d01 * d01);
offset = invDenom - margin_radius;
if (offset > 0.0f)
goto edge_2_3;
invDenom = offset / invDenom;
x += (d00 *= invDenom);
z += (d01 *= invDenom);
margin_radius += 0.01f;
if (d00 * surf->normal.x + d01 * surf->normal.z < corner_threshold * offset)
continue;
else
goto hasCollision;
}
edge_2_3:
//Edge 2-3
v1x = (f32)(surf->vertex3[0] - surf->vertex2[0]);
v1y = (f32)(surf->vertex3[1] - surf->vertex2[1]);
v1z = (f32)(surf->vertex3[2] - surf->vertex2[2]);
v2x = x - (f32)surf->vertex2[0];
v2y = y - (f32)surf->vertex2[1];
v2z = z - (f32)surf->vertex2[2];
if (v1y != 0.0f) {
v = (v2y / v1y);
if (v < 0.0f || v > 1.0f)
continue;
d00 = v1x * v - v2x;
d01 = v1z * v - v2z;
invDenom = sqrtf(d00 * d00 + d01 * d01);
offset = invDenom - margin_radius;
if (offset > 0.0f)
continue;
invDenom = offset / invDenom;
x += (d00 *= invDenom);
z += (d01 *= invDenom);
margin_radius += 0.01f;
if (d00 * surf->normal.x + d01 * surf->normal.z < corner_threshold * offset)
continue;
else
goto hasCollision;
}
else
continue;
hasCollision:
//! (Unreferenced Walls) Since this only returns the first four walls,
// this can lead to wall interaction being missed. Typically unreferenced walls
// come from only using one wall, however.
@@ -150,6 +271,8 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
numCols++;
}
data->x = x;
data->z = z;
return numCols;
}
@@ -220,23 +343,43 @@ s32 find_wall_collisions(struct WallCollisionData *colData) {
* CEILINGS *
**************************************************/
void add_ceil_margin(s32 *x, s32 *z, Vec3s target1, Vec3s target2, f32 margin) {
register f32 diff_x, diff_z, invDenom;
f32 newX = (f32)*x;
f32 newZ = (f32)*z;
diff_x = target1[0] - newX + target2[0] - newX;
diff_z = target1[2] - newZ + target2[2] - newZ;
invDenom = margin / sqrtf(diff_x * diff_x + diff_z * diff_z);
*x += diff_x * invDenom;
*z += diff_z * invDenom;
}
/**
* Iterate through the list of ceilings and find the first ceiling over a given point.
*/
static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z, f32 *pheight) {
register struct Surface *surf;
register s32 x1, z1, x2, z2, x3, z3;
s32 x1, z1, x2, z2, x3, z3;
f32 nx, ny, nz, oo, height;
struct Surface *ceil = NULL;
*pheight = CELL_HEIGHT_LIMIT;
f32 newHeight;
const f32 margin = 1.5f;
ceil = NULL;
// Stay in this loop until out of ceilings.
while (surfaceNode != NULL) {
surf = surfaceNode->surface;
surfaceNode = surfaceNode->next;
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
if (surf->type != SURFACE_HANGABLE)
add_ceil_margin(&x1, &z1, surf->vertex2, surf->vertex3, margin);
z2 = surf->vertex2[2];
x2 = surf->vertex2[0];
if (surf->type != SURFACE_HANGABLE)
add_ceil_margin(&x2, &z2, surf->vertex3, surf->vertex1, margin);
// Checking if point is in bounds of the triangle laterally.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) > 0) {
continue;
@@ -244,6 +387,8 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
// Slight optimization by checking these later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if (surf->type != SURFACE_HANGABLE)
add_ceil_margin(&x3, &z3, surf->vertex1, surf->vertex2, margin);
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) > 0) {
continue;
}
@@ -274,7 +419,7 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
continue;
}
// Checks for ceiling interaction
if (y > height) {
if (/*y > height*/ y - (height - -78.0f) > 0.0f) {
continue;
}
if (y >= surf->upperY) {

View File

@@ -541,6 +541,20 @@ struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 ra
return wall;
}
void resolve_and_return_wall_collisions_frame(Vec3f pos, f32 offset, f32 radius, struct WallCollisionData *collisionData) {
collisionData->x = pos[0];
collisionData->y = pos[1];
collisionData->z = pos[2];
collisionData->radius = radius;
collisionData->offsetY = offset;
find_wall_collisions(collisionData);
pos[0] = collisionData->x;
pos[1] = collisionData->y;
pos[2] = collisionData->z;
}
/**
* Finds the ceiling from a vec3f horizontally and a height (with 80 vertical buffer).
*/

View File

@@ -29,6 +29,7 @@ void mario_set_forward_vel(struct MarioState *m, f32 speed);
s32 mario_get_floor_class(struct MarioState *m);
u32 mario_get_terrain_sound_addend(struct MarioState *m);
struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius);
void resolve_and_return_wall_collisions_frame(Vec3f pos, f32 offset, f32 radius, struct WallCollisionData *collisionData);
f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil);
s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw);
u32 mario_floor_is_slippery(struct MarioState *m);

View File

@@ -256,23 +256,32 @@ s32 stationary_ground_step(struct MarioState *m) {
}
static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
UNUSED struct Surface *lowerWall;
struct Surface *upperWall;
//struct Surface *lowerWall;
//struct Surface *upperWall;
struct WallCollisionData lowerWall;
struct WallCollisionData upperWall;
struct Surface *ceil;
struct Surface *floor;
f32 ceilHeight;
f32 floorHeight;
f32 waterLevel;
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 24.0f);
upperWall = resolve_and_return_wall_collisions(nextPos, 60.0f, 50.0f);
s16 i;
s16 wallDYaw;
s32 oldWallDYaw;
s32 absWallDYaw;
// lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 24.0f);
// upperWall = resolve_and_return_wall_collisions(nextPos, 60.0f, 50.0f);
resolve_and_return_wall_collisions_frame(nextPos, 30.0f, 24.0f, &lowerWall);
resolve_and_return_wall_collisions_frame(nextPos, 60.0f, 50.0f, &upperWall);
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
ceilHeight = vec3f_find_ceil(nextPos, nextPos[1], &ceil);
waterLevel = find_water_level(nextPos[0], nextPos[2]);
m->wall = upperWall;
//m->wall = upperWall;
if (floor == NULL) {
return GROUND_STEP_HIT_WALL_STOP_QSTEPS;
@@ -303,20 +312,32 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) {
m->floor = floor;
m->floorHeight = floorHeight;
if (upperWall != NULL) {
s16 wallDYaw = atan2s(upperWall->normal.z, upperWall->normal.x) - m->faceAngle[1];
if (wallDYaw >= 0x2AAA && wallDYaw <= 0x5555) {
return GROUND_STEP_NONE;
}
if (wallDYaw <= -0x2AAA && wallDYaw >= -0x5555) {
return GROUND_STEP_NONE;
}
return GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS;
if (m->wall != NULL) {
oldWallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1];
oldWallDYaw = oldWallDYaw < 0 ? -oldWallDYaw : oldWallDYaw;
}
else
oldWallDYaw = 0;
return GROUND_STEP_NONE;
for (i = 0; i < upperWall.numWalls; i++) {
wallDYaw = atan2s(upperWall.walls[i]->normal.z, upperWall.walls[i]->normal.x) - m->faceAngle[1];
absWallDYaw = wallDYaw < 0 ? -wallDYaw : wallDYaw;
if (absWallDYaw > oldWallDYaw) {
oldWallDYaw = absWallDYaw;
m->wall = upperWall.walls[i];
}
if (wallDYaw >= 0x2AAA && wallDYaw <= 0x5555) {
continue;
}
if (wallDYaw <= -0x2AAA && wallDYaw >= -0x5555) {
continue;
}
return GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS;
}
return GROUND_STEP_NONE;
}
s32 perform_ground_step(struct MarioState *m) {
@@ -324,6 +345,7 @@ s32 perform_ground_step(struct MarioState *m) {
u32 stepResult;
Vec3f intendedPos;
m->wall = NULL;
for (i = 0; i < 4; i++) {
intendedPos[0] = m->pos[0] + m->floor->normal.y * (m->vel[0] / 4.0f);
intendedPos[2] = m->pos[2] + m->floor->normal.y * (m->vel[2] / 4.0f);
@@ -345,9 +367,9 @@ s32 perform_ground_step(struct MarioState *m) {
return stepResult;
}
u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedPos, Vec3f nextPos) {
struct Surface *ledgeFloor;
Vec3f ledgePos;
struct Surface *check_ledge_grab(struct MarioState *m, struct Surface *grabbedWall, struct Surface *wall, Vec3f intendedPos, Vec3f nextPos, Vec3f ledgePos, struct Surface **ledgeFloor) {
//struct Surface *ledgeFloor;
//Vec3f ledgePos;
f32 displacementX;
f32 displacementZ;
@@ -355,13 +377,17 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP
return FALSE;
}
//Return the already grabbed wall if Mario is moving into it more than the newly tested wall
if (grabbedWall != NULL &&
grabbedWall->normal.x * m->vel[0] + grabbedWall->normal.z * m->vel[2] < wall->normal.x * m->vel[0] + wall->normal.z * m->vel[2])
return grabbedWall;
displacementX = nextPos[0] - intendedPos[0];
displacementZ = nextPos[2] - intendedPos[2];
// Only ledge grab if the wall displaced Mario in the opposite direction of
// his velocity.
if (displacementX * m->vel[0] + displacementZ * m->vel[2] > 0.0f) {
return FALSE;
return grabbedWall;
}
//! Since the search for floors starts at y + 160, we will sometimes grab
@@ -371,35 +397,93 @@ u32 check_ledge_grab(struct MarioState *m, struct Surface *wall, Vec3f intendedP
ledgePos[1] = find_floor(ledgePos[0], nextPos[1] + 160.0f, ledgePos[2], &ledgeFloor);
if (ledgePos[1] - nextPos[1] <= 100.0f) {
return FALSE;
return grabbedWall;
}
vec3f_copy(m->pos, ledgePos);
m->floor = ledgeFloor;
m->floorHeight = ledgePos[1];
// vec3f_copy(m->pos, ledgePos);
// m->floor = ledgeFloor;
// m->floorHeight = ledgePos[1];
m->floorAngle = atan2s(ledgeFloor->normal.z, ledgeFloor->normal.x);
// m->floorAngle = atan2s(ledgeFloor->normal.z, ledgeFloor->normal.x);
m->faceAngle[0] = 0;
m->faceAngle[1] = atan2s(wall->normal.z, wall->normal.x) + 0x8000;
return TRUE;
// m->faceAngle[0] = 0;
// m->faceAngle[1] = atan2s(wall->normal.z, wall->normal.x) + 0x8000;
// return TRUE;
return wall;
}
s32 bonk_or_hit_lava_wall(struct MarioState *m, struct WallCollisionData *wallData) {
s16 i;
s16 wallDYaw;
s32 oldWallDYaw;
s32 absWallDYaw;
s32 result;
result = AIR_STEP_NONE;
if (m->wall != NULL) {
oldWallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1];
oldWallDYaw = oldWallDYaw < 0 ? -oldWallDYaw : oldWallDYaw;
}
else
oldWallDYaw = 0;
for (i = 0; i < wallData->numWalls; i++) {
if (wallData->walls[i] != NULL) {
wallDYaw = atan2s(wallData->walls[i]->normal.z, wallData->walls[i]->normal.x) - m->faceAngle[1];
if (wallData->walls[i]->type == SURFACE_BURNING) {
m->wall = wallData->walls[i];
return AIR_STEP_HIT_LAVA_WALL;
}
//Update wall reference (bonked wall) only if the new wall has a better facing angle
absWallDYaw = wallDYaw < 0 ? -wallDYaw : wallDYaw;
if (absWallDYaw > oldWallDYaw) {
oldWallDYaw = absWallDYaw;
m->wall = wallData->walls[i];
if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
m->flags |= MARIO_UNKNOWN_30;
result = AIR_STEP_HIT_WALL;
}
}
}
}
return result;
}
s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepArg) {
s16 wallDYaw;
s16 i;
s32 stepResult;
Vec3f nextPos;
struct Surface *upperWall;
struct Surface *lowerWall;
// struct Surface *upperWall;
// struct Surface *lowerWall;
Vec3f ledgePos;
struct WallCollisionData upperWall;
struct WallCollisionData lowerWall;
struct Surface *ceil;
struct Surface *floor;
struct Surface *grabbedWall;
struct Surface *ledgeFloor;
f32 ceilHeight;
f32 floorHeight;
f32 waterLevel;
grabbedWall = NULL;
stepResult = AIR_STEP_NONE;
vec3f_copy(nextPos, intendedPos);
upperWall = resolve_and_return_wall_collisions(nextPos, 150.0f, 50.0f);
lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f);
// upperWall = resolve_and_return_wall_collisions(nextPos, 150.0f, 50.0f);
// lowerWall = resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f);
resolve_and_return_wall_collisions_frame(nextPos, 150.0f, 50.0f, &upperWall);
resolve_and_return_wall_collisions_frame(nextPos, 30.0f, 50.0f, &lowerWall);
floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor);
ceilHeight = vec3f_find_ceil(nextPos, nextPos[1], &ceil);
@@ -463,41 +547,70 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr
}
m->pos[1] = nextPos[1];
return AIR_STEP_HIT_WALL;
return AIR_STEP_HIT_WALL; //change to 0 if you dont want ceil bonks
}
//! When the wall is not completely vertical or there is a slight wall
// misalignment, you can activate these conditions in unexpected situations
if ((stepArg & AIR_STEP_CHECK_LEDGE_GRAB) && upperWall == NULL && lowerWall != NULL) {
if (check_ledge_grab(m, lowerWall, intendedPos, nextPos)) {
return AIR_STEP_GRABBED_LEDGE;
}
// if ((stepArg & AIR_STEP_CHECK_LEDGE_GRAB) && upperWall == NULL && lowerWall != NULL) {
// if (check_ledge_grab(m, lowerWall, intendedPos, nextPos)) {
// return AIR_STEP_GRABBED_LEDGE;
// }
vec3f_copy(m->pos, nextPos);
m->floor = floor;
m->floorHeight = floorHeight;
return AIR_STEP_NONE;
}
// vec3f_copy(m->pos, nextPos);
// m->floor = floor;
// m->floorHeight = floorHeight;
// return AIR_STEP_NONE;
// }
if ((stepArg & AIR_STEP_CHECK_LEDGE_GRAB) && upperWall.numWalls == 0) {
for (i = 0; i < lowerWall.numWalls; i++)
if ((grabbedWall = check_ledge_grab(m, grabbedWall, lowerWall.walls[i], intendedPos, nextPos, ledgePos, &ledgeFloor)))
stepResult = AIR_STEP_GRABBED_LEDGE;
if (stepResult == AIR_STEP_GRABBED_LEDGE)
{
vec3f_copy(m->pos, ledgePos);
m->floor = ledgeFloor;
m->floorHeight = ledgePos[1];
m->floorAngle = atan2s(ledgeFloor->normal.z, ledgeFloor->normal.x);
m->faceAngle[0] = 0;
m->faceAngle[1] = atan2s(grabbedWall->normal.z, grabbedWall->normal.x) + 0x8000;
}
else {
vec3f_copy(m->pos, nextPos);
m->floor = floor;
m->floorHeight = floorHeight;
}
return stepResult;
}
vec3f_copy(m->pos, nextPos);
m->floor = floor;
m->floorHeight = floorHeight;
if (upperWall != NULL || lowerWall != NULL) {
m->wall = upperWall != NULL ? upperWall : lowerWall;
wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1];
stepResult = bonk_or_hit_lava_wall(m, &upperWall);
if (stepResult != AIR_STEP_NONE)
return stepResult;
if (m->wall->type == SURFACE_BURNING) {
return AIR_STEP_HIT_LAVA_WALL;
}
return bonk_or_hit_lava_wall(m, &lowerWall);
if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
m->flags |= MARIO_UNKNOWN_30;
return AIR_STEP_HIT_WALL;
}
}
// if (upperWall != NULL || lowerWall != NULL) {
// m->wall = upperWall != NULL ? upperWall : lowerWall;
// wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1];
return AIR_STEP_NONE;
// if (m->wall->type == SURFACE_BURNING) {
// return AIR_STEP_HIT_LAVA_WALL;
// }
// if (wallDYaw < -0x6000 || wallDYaw > 0x6000) {
// m->flags |= MARIO_UNKNOWN_30;
// return AIR_STEP_HIT_WALL;
// }
// }
// return AIR_STEP_NONE;
}
void apply_twirl_gravity(struct MarioState *m) {