diff --git a/include/config.h b/include/config.h index 02c57973..2d2eb2eb 100644 --- a/include/config.h +++ b/include/config.h @@ -58,10 +58,6 @@ #endif // DISABLE_EXIT_COURSE // -- MOVEMENT SETTINGS -- -// Change the movement speed when hanging from a ceiling (the vanilla value is 4.f) -#define HANGING_SPEED 12.f -// Makes Mario face the direction of the analog stick directly while hanging from a ceiling, without doing "semicircles" -#define TIGHTER_HANGING_CONTROLS // Fixes Mario's turn radius by making it dependent on forward speed. // Modes: // 0 is vanilla behavior. @@ -69,6 +65,14 @@ // 2 is similar to mode 1, but a bit further from vanilla, and allows instant turnaround if Mario is moving slower than a certain threshold. // 3 is instant turning to the intended direction regardless of speed and angle. #define GROUND_TURN_MODE 0 +// Improved hanging: +// - Doesn't require holding down the A button +// - Percise turning control () +// - Preventis falling from the edges +// (Arceveti) +#define BETTER_HANGING +// Change the movement speed when hanging from a ceiling (the vanilla value is 4.0f, has no effect if BETTER_HANGING is enabled) +#define HANGING_SPEED 12.0f // Disables fall damage #define NO_FALL_DAMAGE // Disables the scream that mario makes when falling off a great height (this is separate from actual fall damage) @@ -180,7 +184,7 @@ // Uncomment this define and set a test level in order to boot straight into said level. // This allows you to quickly test the level you're working on. // If you want the game to boot normally, just comment out the define again. -//#define TEST_LEVEL LEVEL_BOB +// #define TEST_LEVEL LEVEL_BOB // Custom debug mode. Press DPAD left to show the debug UI. Press DPAD right to enter the noclip mode. //#define CUSTOM_DEBUG // Include Puppyprint, a display library for text and large images. Also includes a custom, enhanced performance profiler. diff --git a/include/sm64.h b/include/sm64.h index e991781f..cf0b3069 100644 --- a/include/sm64.h +++ b/include/sm64.h @@ -83,7 +83,7 @@ #define INPUT_OFF_FLOOR /* 0x0004 */ (1 << 2) #define INPUT_ABOVE_SLIDE /* 0x0008 */ (1 << 3) #define INPUT_FIRST_PERSON /* 0x0010 */ (1 << 4) -#define INPUT_UNKNOWN_5 /* 0x0020 */ (1 << 5) +#define INPUT_IDLE /* 0x0020 */ (1 << 5) #define INPUT_SQUISHED /* 0x0040 */ (1 << 6) #define INPUT_A_DOWN /* 0x0080 */ (1 << 7) #define INPUT_IN_POISON_GAS /* 0x0100 */ (1 << 8) diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index 7adf2544..72492df7 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -38,4 +38,4 @@ s32 find_water_level_and_floor(s32 x, s32 z, struct Surface **pfloor); s32 find_water_level(s32 x, s32 z); s32 find_poison_gas_level(s32 x, s32 z); void debug_surface_list_info(f32 xPos, f32 zPos); -extern void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos, s32 flags); +void find_surface_on_ray(Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos, s32 flags); diff --git a/src/game/mario.c b/src/game/mario.c index 5691c028..7cef3c9d 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1410,7 +1410,7 @@ void update_mario_inputs(struct MarioState *m) { } if (!(m->input & (INPUT_NONZERO_ANALOG | INPUT_A_PRESSED))) { - m->input |= INPUT_UNKNOWN_5; + m->input |= INPUT_IDLE; } // These 3 flags are defined by Bowser stomping attacks diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index 610f2060..2baa0912 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -330,15 +330,30 @@ s32 perform_hanging_step(struct MarioState *m, Vec3f nextPos) { s32 update_hang_moving(struct MarioState *m) { s32 stepResult; Vec3f nextPos; +#ifdef BETTER_HANGING + f32 maxSpeed = (m->intendedMag / 2.0f); +#else f32 maxSpeed = HANGING_SPEED; +#endif m->forwardVel += 1.0f; if (m->forwardVel > maxSpeed) { m->forwardVel = maxSpeed; } -#ifdef TIGHTER_HANGING_CONTROLS - m->faceAngle[1] = m->intendedYaw; +#ifdef BETTER_HANGING + s16 turnRange = 0x800; + s16 dYaw = abs_angle_diff(m->faceAngle[1], m->intendedYaw); // 0x0 is turning forwards, 0x8000 is turning backwards + if (m->forwardVel < 0.0f) { // Don't modify Mario's speed and turn radius if Mario is moving backwards + // Flip controls when moving backwards so Mario still moves towards intendedYaw + m->intendedYaw += 0x8000; + } else if (dYaw > 0x4000) { // Only modify Mario's speed and turn radius if Mario is turning around + // Reduce Mario's forward speed by the turn amount, so Mario won't move off sideward from the intended angle when turning around. + m->forwardVel *= ((coss(dYaw) + 1.0f) / 2.0f); // 1.0f is turning forwards, 0.0f is turning backwards + // Increase turn speed if forwardVel is lower and intendedMag is higher + turnRange *= (2.0f - (ABSF(m->forwardVel) / MAX(m->intendedMag, __FLT_EPSILON__))); // 1.0f front, 2.0f back + } + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, turnRange); #else m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); #endif @@ -370,6 +385,9 @@ void update_hang_stationary(struct MarioState *m) { m->pos[1] = m->ceilHeight - 160.0f; vec3f_copy(m->vel, gVec3fZero); vec3f_copy(m->marioObj->header.gfx.pos, m->pos); +#ifdef BETTER_HANGING + vec3_set(m->marioObj->header.gfx.angle, 0x0, m->faceAngle[1], 0x0); +#endif } s32 act_start_hanging(struct MarioState *m) { @@ -380,14 +398,13 @@ s32 act_start_hanging(struct MarioState *m) { #else m->actionTimer++; #endif - - if ((m->input & INPUT_NONZERO_ANALOG) && m->actionTimer >= 31) { - return set_mario_action(m, ACT_HANGING, 0); - } - - if (!(m->input & INPUT_A_DOWN)) { - return set_mario_action(m, ACT_FREEFALL, 0); - } +#ifdef BETTER_HANGING + if ((m->input & INPUT_NONZERO_ANALOG) && (m->intendedMag > 16.0f) && (m->actionTimer > 1)) return set_mario_action(m, ACT_HANGING, 0); + if ( m->input & (INPUT_A_PRESSED | INPUT_B_PRESSED) ) return set_mario_action(m, ACT_FREEFALL, 0); +#else + if ((m->input & INPUT_NONZERO_ANALOG) && (m->actionTimer >= 31) ) return set_mario_action(m, ACT_HANGING, 0); + if (!(m->input & INPUT_A_DOWN) ) return set_mario_action(m, ACT_FREEFALL, 0); +#endif if (m->input & INPUT_Z_PRESSED) { return set_mario_action(m, ACT_GROUND_POUND, 0); @@ -414,9 +431,11 @@ s32 act_hanging(struct MarioState *m) { return set_mario_action(m, ACT_HANG_MOVING, m->actionArg); } - if (!(m->input & INPUT_A_DOWN)) { - return set_mario_action(m, ACT_FREEFALL, 0); - } +#ifdef BETTER_HANGING + if (m->input & (INPUT_A_PRESSED | INPUT_B_PRESSED)) return set_mario_action(m, ACT_FREEFALL, 0); +#else + if (!(m->input & INPUT_A_DOWN) ) return set_mario_action(m, ACT_FREEFALL, 0); +#endif if (m->input & INPUT_Z_PRESSED) { return set_mario_action(m, ACT_GROUND_POUND, 0); @@ -438,9 +457,11 @@ s32 act_hanging(struct MarioState *m) { } s32 act_hang_moving(struct MarioState *m) { - if (!(m->input & INPUT_A_DOWN)) { - return set_mario_action(m, ACT_FREEFALL, 0); - } +#ifdef BETTER_HANGING + if (m->input & (INPUT_A_PRESSED | INPUT_B_PRESSED)) return set_mario_action(m, ACT_FREEFALL, 0); +#else + if (!(m->input & INPUT_A_DOWN) ) return set_mario_action(m, ACT_FREEFALL, 0); +#endif if (m->input & INPUT_Z_PRESSED) { return set_mario_action(m, ACT_GROUND_POUND, 0); @@ -450,11 +471,11 @@ s32 act_hang_moving(struct MarioState *m) { return set_mario_action(m, ACT_FREEFALL, 0); } - if (m->actionArg & 1) { - set_mario_animation(m, MARIO_ANIM_MOVE_ON_WIRE_NET_RIGHT); - } else { - set_mario_animation(m, MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT); - } +#ifdef BETTER_HANGING + set_mario_anim_with_accel(m, ((m->actionArg & 1) ? MARIO_ANIM_MOVE_ON_WIRE_NET_RIGHT : MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT), ((m->forwardVel + 1.0f) * 0x2000)); +#else + set_mario_animation(m, ((m->actionArg & 1) ? MARIO_ANIM_MOVE_ON_WIRE_NET_RIGHT : MARIO_ANIM_MOVE_ON_WIRE_NET_LEFT)); +#endif if (m->marioObj->header.gfx.animInfo.animFrame == 12) { play_sound(SOUND_ACTION_HANGING_STEP, m->marioObj->header.gfx.cameraToObject); @@ -463,16 +484,25 @@ s32 act_hang_moving(struct MarioState *m) { #endif } +#ifdef BETTER_HANGING + if (m->input & INPUT_IDLE) { + if (m->marioObj->header.gfx.animInfo.animFrame > 6) m->actionArg ^= 1; + set_mario_action(m, ACT_HANGING, m->actionArg); + } else if (is_anim_past_end(m)) { + m->actionArg ^= 1; + } + update_hang_moving(m); +#else if (is_anim_past_end(m)) { m->actionArg ^= 1; if (m->input & INPUT_UNKNOWN_5) { return set_mario_action(m, ACT_HANGING, m->actionArg); } } - if (update_hang_moving(m) == HANG_LEFT_CEIL) { set_mario_action(m, ACT_FREEFALL, 0); } +#endif return FALSE; } diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index fe9f7f17..5664eb9c 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -831,7 +831,7 @@ s32 act_walking(struct MarioState *m) { return TRUE; } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return begin_braking_action(m); } @@ -928,7 +928,7 @@ s32 act_hold_walking(struct MarioState *m) { return set_jumping_action(m, ACT_HOLD_JUMP, 0); } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_HOLD_DECELERATING, 0); } @@ -970,7 +970,7 @@ s32 act_hold_heavy_walking(struct MarioState *m) { return drop_and_set_mario_action(m, ACT_BEGIN_SLIDING, 0); } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_HOLD_HEAVY_IDLE, 0); } @@ -1003,7 +1003,7 @@ s32 act_turning_around(struct MarioState *m) { return set_jumping_action(m, ACT_SIDE_FLIP, 0); } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_BRAKING, 0); } @@ -1298,7 +1298,7 @@ s32 act_crawling(struct MarioState *m) { return TRUE; } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_STOP_CRAWLING, 0); } diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index fbcd170c..d1bc44e1 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -1242,7 +1242,7 @@ static s32 act_metal_water_walking(struct MarioState *m) { return set_mario_action(m, ACT_METAL_WATER_JUMP, 0); } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_METAL_WATER_STANDING, 0); } @@ -1282,7 +1282,7 @@ static s32 act_hold_metal_water_walking(struct MarioState *m) { return set_mario_action(m, ACT_HOLD_METAL_WATER_JUMP, 0); } - if (m->input & INPUT_UNKNOWN_5) { + if (m->input & INPUT_IDLE) { return set_mario_action(m, ACT_HOLD_METAL_WATER_STANDING, 0); }