Configurable wall kick angle in degrees

This commit is contained in:
Arceveti
2021-09-27 14:00:10 -07:00
parent ae91a98422
commit 3f4728e337
7 changed files with 59 additions and 93 deletions

View File

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

View File

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

View File

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

View File

@@ -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))
/**

View File

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

View File

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

View File

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