You've already forked Microtransactions64
mirror of
https://github.com/Print-and-Panic/Microtransactions64.git
synced 2026-01-21 10:17:19 -08:00
Merge pull request #2 from Cheezepin/master
Frame's patch (rounded corners and quarter-step shenanigans)
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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).
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user