diff --git a/include/config.h b/include/config.h index f8c64113..fc87979a 100644 --- a/include/config.h +++ b/include/config.h @@ -63,7 +63,12 @@ // 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. -//#define FIX_GROUND_TURN_RADIUS +// Modes: +// 0 is vanilla behavior. +// 1 is similar to vanilla, but prevents Mario from moving in the wrong direction, and allows finer control with the analog stick. +// 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 // 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) diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index d0f9e055..fe9f7f17 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -435,13 +435,12 @@ s32 update_decelerating_speed(struct MarioState *m) { } s32 analog_stick_held_back(struct MarioState *m) { - s16 intendedDYaw = m->intendedYaw - m->faceAngle[1]; - return intendedDYaw < -0x471C || intendedDYaw > 0x471C; + s16 intendedDYaw = (m->intendedYaw - m->faceAngle[1]); + return ((intendedDYaw < -0x471C) || (intendedDYaw > 0x471C)); } void update_walking_speed(struct MarioState *m) { f32 maxTargetSpeed; - f32 targetSpeed; if (m->floor != NULL && m->floor->type == SURFACE_SLOW) { maxTargetSpeed = 24.0f; @@ -449,7 +448,7 @@ void update_walking_speed(struct MarioState *m) { maxTargetSpeed = 32.0f; } - targetSpeed = m->intendedMag < maxTargetSpeed ? m->intendedMag : maxTargetSpeed; + f32 targetSpeed = m->intendedMag < maxTargetSpeed ? m->intendedMag : maxTargetSpeed; if (m->quicksandDepth > 10.0f) { targetSpeed *= 6.25 / m->quicksandDepth; @@ -467,28 +466,46 @@ void update_walking_speed(struct MarioState *m) { m->forwardVel = 48.0f; } -#ifdef FIX_GROUND_TURN_RADIUS +#if GROUND_TURN_MODE == 0 // Vanilla behavior. + m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); +#elif GROUND_TURN_MODE == 1 // Similar to vanilla, but prevents Mario from moving in the wrong direction when turning around, and allows finer control with the analog stick. + 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); +#elif GROUND_TURN_MODE == 2 // similar to mode 1, but a bit further from vanilla, and allows instant turnaround if Mario is moving slower than a certain threshold. if ((m->forwardVel < 0.0f) && (m->heldObj == NULL) && !(m->action & ACT_FLAG_SHORT_HITBOX)) { + // Flip Mario if he is moving backwards m->faceAngle[1] += 0x8000; m->forwardVel *= -1.0f; } if (analog_stick_held_back(m) && (m->heldObj == NULL) && !(m->action & ACT_FLAG_SHORT_HITBOX)) { + // Turn around instantly set_mario_action(m, ACT_TURNING_AROUND, 0); if (m->forwardVel < 10.0f) { m->faceAngle[1] = m->intendedYaw; } } else { - s16 turnRange = (0xFFF - (m->forwardVel * 0x20)); + // Scale the turn radius by forwardVel + s16 turnRange = (0x1000 - (m->forwardVel * 0x20)); if (turnRange < 0x800) { - turnRange = 0x800; + turnRange = 0x800; // Clamp the minimum radius (vanilla radius, 0x800) set_mario_action(m, ACT_TURNING_AROUND, 0); - } else if (turnRange > 0xFFF) { - turnRange = 0xFFF; + } else if (turnRange > 0x1000) { + turnRange = 0x1000; // Clamp the maximum radius (0x1000) } m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, turnRange); } -#else - m->faceAngle[1] = approach_angle(m->faceAngle[1], m->intendedYaw, 0x800); +#elif GROUND_TURN_MODE == 3 // Instant turn. + m->faceAngle[1] = m->intendedYaw; #endif apply_slope_accel(m); }