From 3f4728e33778cb46fb602412f7a1238e55d8b984 Mon Sep 17 00:00:00 2001 From: Arceveti <73617174+Arceveti@users.noreply.github.com> Date: Mon, 27 Sep 2021 14:00:10 -0700 Subject: [PATCH] Configurable wall kick angle in degrees --- include/config.h | 4 +- src/engine/math_util.c | 6 ++ src/engine/math_util.h | 6 ++ src/game/camera.h | 6 -- src/game/mario_step.c | 115 +++++++++++++++----------------------- src/game/object_helpers.c | 14 ----- src/game/object_helpers.h | 1 - 7 files changed, 59 insertions(+), 93 deletions(-) diff --git a/include/config.h b/include/config.h index 7665ea0c..9d8b9189 100644 --- a/include/config.h +++ b/include/config.h @@ -93,8 +93,8 @@ #define HANGING_FIX // The last frame that will be considered a firsty when wallkicking #define FIRSTY_LAST_FRAME 1 -// 46 degree walkicks -//#define WALLKICKS_46_DEGREES +// The maximum angle the player can wall kick, in degrees. 0..90 +#define WALL_KICK_DEGREES 45 // Disable BLJs and crush SimpleFlips's dreams //#define DISABLE_BLJ diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 0dc5d8f5..80c3c101 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -869,6 +869,12 @@ s32 approach_s16_asymptotic(s16 current, s16 target, s16 divisor) { return current; } +s16 abs_angle_diff(s16 a0, s16 a1) { + s16 diff = (a1 - a0); + if (diff == -0x8000) diff = -0x7FFF; + return ABSI(diff); +} + /** * Helper function for atan2s. Does a look up of the arctangent of y/x assuming * the resulting angle is in range [0, 0x2000] (1/8 of a circle). diff --git a/src/engine/math_util.h b/src/engine/math_util.h index 17a605c6..41c403e2 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -5,6 +5,11 @@ #include "types.h" +/** + * Converts an angle in degrees to sm64's s16 angle units. For example, DEGREES(90) == 0x4000 + * This should be used mainly to make camera code clearer at first glance. + */ +#define DEGREES(x) ((x) * 0x10000 / 360) /* * The sine and cosine tables overlap, but "#define gCosineTable (gSineTable + @@ -412,6 +417,7 @@ s32 approach_f32_asymptotic_bool(f32 *current, f32 target, f32 multiplier); f32 approach_f32_asymptotic(f32 current, f32 target, f32 multiplier); s32 approach_s16_asymptotic_bool(s16 *current, s16 target, s16 divisor); s32 approach_s16_asymptotic(s16 current, s16 target, s16 divisor); +s16 abs_angle_diff(s16 a0, s16 a1); s16 atan2s(f32 y, f32 x); f32 atan2f(f32 a, f32 b); void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c); diff --git a/src/game/camera.h b/src/game/camera.h index b4bf74e6..122fb35d 100644 --- a/src/game/camera.h +++ b/src/game/camera.h @@ -21,12 +21,6 @@ * @see camera.c */ -/** - * Converts an angle in degrees to sm64's s16 angle units. For example, DEGREES(90) == 0x4000 - * This should be used mainly to make camera code clearer at first glance. - */ -#define DEGREES(x) ((x) * 0x10000 / 360) - #define LEVEL_AREA_INDEX(levelNum, areaNum) (((levelNum) << 4) + (areaNum)) /** diff --git a/src/game/mario_step.c b/src/game/mario_step.c index c3ddeb9b..3a2d5002 100644 --- a/src/game/mario_step.c +++ b/src/game/mario_step.c @@ -63,13 +63,15 @@ void transfer_bully_speed(struct BullyCollisionData *obj1, struct BullyCollision f32 projectedV1 = ( rx * obj1->velX + rz * obj1->velZ) / rzx; f32 projectedV2 = (-rx * obj2->velX - rz * obj2->velZ) / rzx; - // Kill speed along r. Convert one object's speed along r and transfer it to - // the other object. - obj2->velX += obj2->conversionRatio * projectedV1 * rx - projectedV2 * -rx; - obj2->velZ += obj2->conversionRatio * projectedV1 * rz - projectedV2 * -rz; - - obj1->velX += -projectedV1 * rx + obj1->conversionRatio * projectedV2 * -rx; - obj1->velZ += -projectedV1 * rz + obj1->conversionRatio * projectedV2 * -rz; + // Kill speed along r. Convert one object's speed along r and transfer it to the other object. + f32 p1x = projectedV1 * rx; + f32 p1z = projectedV1 * rz; + f32 p2x = projectedV2 * -rx; + f32 p2z = projectedV2 * -rz; + obj2->velX += (obj2->conversionRatio * p1x) - p2x; + obj2->velZ += (obj2->conversionRatio * p1z) - p2z; + obj1->velX += -p1x + (obj1->conversionRatio * p2x); + obj1->velZ += -p1z + (obj1->conversionRatio * p2z); //! Bully battery } @@ -259,26 +261,20 @@ s32 stationary_ground_step(struct MarioState *m) { } static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) { - struct WallCollisionData lowerWall; - struct WallCollisionData upperWall; - struct Surface *ceil; - struct Surface *floor; - f32 ceilHeight; - f32 floorHeight; - f32 waterLevel; + struct WallCollisionData lowerWall, upperWall; + struct Surface *ceil, *floor; s16 i; s16 wallDYaw; s32 oldWallDYaw; - s32 absWallDYaw; resolve_and_return_wall_collisions(nextPos, 30.0f, 24.0f, &lowerWall); resolve_and_return_wall_collisions(nextPos, 60.0f, 50.0f, &upperWall); - floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); - ceilHeight = find_ceil(nextPos[0], nextPos[1] + 3.0f, nextPos[2], &ceil); + f32 floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); + f32 ceilHeight = find_ceil(nextPos[0], nextPos[1] + 3.0f, nextPos[2], &ceil); - waterLevel = find_water_level(nextPos[0], nextPos[2]); + f32 waterLevel = find_water_level(nextPos[0], nextPos[2]); if (floor == NULL) { return GROUND_STEP_HIT_WALL_STOP_QSTEPS; @@ -310,24 +306,20 @@ static s32 perform_ground_quarter_step(struct MarioState *m, Vec3f nextPos) { if (m->wall != NULL) { oldWallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1]; - oldWallDYaw = oldWallDYaw < 0 ? -oldWallDYaw : oldWallDYaw; + oldWallDYaw = ABSI(oldWallDYaw); } else { - oldWallDYaw = 0; + oldWallDYaw = 0x0; } 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; + wallDYaw = abs_angle_diff(atan2s(upperWall.walls[i]->normal.z, upperWall.walls[i]->normal.x), m->faceAngle[1]); + if (wallDYaw > oldWallDYaw) { + oldWallDYaw = wallDYaw; set_mario_wall(m, upperWall.walls[i]); } if (wallDYaw >= 0x2AAA && wallDYaw <= 0x5555) { continue; } - if (wallDYaw <= -0x2AAA && wallDYaw >= -0x5555) { - continue; - } return GROUND_STEP_HIT_WALL_CONTINUE_QSTEPS; } @@ -364,8 +356,7 @@ s32 perform_ground_step(struct MarioState *m) { } struct Surface *check_ledge_grab(struct MarioState *m, struct Surface *grabbedWall, struct Surface *wall, Vec3f intendedPos, Vec3f nextPos, Vec3f ledgePos, struct Surface **ledgeFloor) { - f32 displacementX; - f32 displacementZ; + f32 displacementX, displacementZ; if (m->vel[1] > 0) { return FALSE; @@ -401,38 +392,32 @@ s32 bonk_or_hit_lava_wall(struct MarioState *m, struct WallCollisionData *wallDa s16 i; s16 wallDYaw; s32 oldWallDYaw; - s32 absWallDYaw; - s32 result; - result = AIR_STEP_NONE; + s32 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; + oldWallDYaw = ABSI(oldWallDYaw); + } else { + oldWallDYaw = 0x0; } - 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) { set_mario_wall(m, 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; + wallDYaw = abs_angle_diff(atan2s(wallData->walls[i]->normal.z, wallData->walls[i]->normal.x), m->faceAngle[1]); + if (wallDYaw > oldWallDYaw) { + oldWallDYaw = wallDYaw; set_mario_wall(m, wallData->walls[i]); - if (wallDYaw < -0x6000 || wallDYaw > 0x6000) { + if (wallDYaw > DEGREES(180 - WALL_KICK_DEGREES)) { m->flags |= MARIO_AIR_HIT_WALL; result = AIR_STEP_HIT_WALL; } } - - } } return result; @@ -440,34 +425,24 @@ s32 bonk_or_hit_lava_wall(struct MarioState *m, struct WallCollisionData *wallDa s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepArg) { s16 i; - s32 stepResult; + s32 stepResult = AIR_STEP_NONE; - Vec3f nextPos; - 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 nextPos, ledgePos; + struct WallCollisionData upperWall, lowerWall; + struct Surface *ceil, *floor, *ledgeFloor; + struct Surface *grabbedWall = NULL; vec3f_copy(nextPos, intendedPos); resolve_and_return_wall_collisions(nextPos, 150.0f, 50.0f, &upperWall); resolve_and_return_wall_collisions(nextPos, 30.0f, 50.0f, &lowerWall); - floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); - ceilHeight = find_ceil(nextPos[0], nextPos[1] + 3.0f, nextPos[2], &ceil); + f32 floorHeight = find_floor(nextPos[0], nextPos[1], nextPos[2], &floor); + f32 ceilHeight = find_ceil(nextPos[0], nextPos[1] + 3.0f, nextPos[2], &ceil); - waterLevel = find_water_level(nextPos[0], nextPos[2]); + f32 waterLevel = find_water_level(nextPos[0], nextPos[2]); - //m->wall = NULL; + // m->wall = NULL; //! The water pseudo floor is not referenced when your intended qstep is // out of bounds, so it won't detect you as landing. @@ -508,12 +483,12 @@ s32 perform_air_quarter_step(struct MarioState *m, Vec3f intendedPos, u32 stepAr m->vel[1] = 0.0f; //! Uses referenced ceiling instead of ceil (ceiling hang upwarp) - #ifdef HANGING_FIX +#ifdef HANGING_FIX if (m->ceil != NULL && m->ceil->type == SURFACE_HANGABLE) { - #else +#else if ((stepArg & AIR_STEP_CHECK_HANG) && m->ceil != NULL && m->ceil->type == SURFACE_HANGABLE) { - #endif +#endif return AIR_STEP_GRABBED_CEILING; } @@ -712,12 +687,12 @@ s32 perform_air_step(struct MarioState *m, u32 stepArg) { vec3s_set(m->marioObj->header.gfx.angle, 0, m->faceAngle[1], 0); /*if (stepResult == AIR_STEP_HIT_WALL && m->wall != NULL) { - wallDYaw = atan2s(m->wall->normal.z, m->wall->normal.x) - m->faceAngle[1]; - if ((stepArg & AIR_STEP_CHECK_BONK) && (wallDYaw < -0x6000 || wallDYaw > 0x6000)) - { - if (m->forwardVel > 16.0f) - mario_bonk_reflection(m, (stepArg & AIR_STEP_BONK_NEGATE_SPEED), m->wall); + wallDYaw = abs_angle_diff(atan2s(m->wall->normal.z, m->wall->normal.x), m->faceAngle[1]); + if ((stepArg & AIR_STEP_CHECK_BONK) && (wallDYaw > DEGREES(180 - WALL_KICK_DEGREES))) { + if (m->forwardVel > 16.0f) { + mario_bonk_reflection(m, (stepArg & AIR_STEP_BONK_NEGATE_SPEED), m->wall); } + } }*/ return stepResult; diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index 472c30c8..d0a37817 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -1268,20 +1268,6 @@ void cur_obj_unused_resolve_wall_collisions(f32 offsetY, f32 radius) { } } -s16 abs_angle_diff(s16 x0, s16 x1) { - s16 diff = x1 - x0; - - if (diff == -0x8000) { - diff = -0x7FFF; - } - - if (diff < 0) { - diff = -diff; - } - - return diff; -} - void cur_obj_move_xz_using_fvel_and_yaw(void) { o->oVelX = o->oForwardVel * sins(o->oMoveAngleYaw); o->oVelZ = o->oForwardVel * coss(o->oMoveAngleYaw); diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index 72fcbb9b..0b79ce2c 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -153,7 +153,6 @@ struct Surface *cur_obj_update_floor_height_and_get_floor(void); void cur_obj_apply_drag_xz(f32 dragStrength); void cur_obj_move_y(f32 gravity, f32 bounciness, f32 buoyancy); void cur_obj_unused_resolve_wall_collisions(f32 offsetY, f32 radius); -s16 abs_angle_diff(s16 x0, s16 x1); void cur_obj_move_xz_using_fvel_and_yaw(void); void cur_obj_move_y_with_terminal_vel(void); void cur_obj_compute_vel_xz(void);