From 3cefb1d4e52deba10262e7412a1727a0427cd6e8 Mon Sep 17 00:00:00 2001 From: Maxime Morel Date: Fri, 23 Oct 2026 10:11:40 +0200 Subject: [PATCH] Look ahead --- port/src/input.c | 10 ++++++++++ src/game/bondview2.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/port/src/input.c b/port/src/input.c index 5fc60b3b..b85afccf 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -507,6 +507,13 @@ static int controlScheme = 0; /* D513 Input.ControlScheme: 0 * the live control (the game honours it in bondview2's stick-pitch path), * so it must stay user-settable there. */ int inputControlScheme(void) { return controlScheme; } + +/* Look ahead (Modern scheme): set when the right stick or mouse pitched the + * view, the equivalent of the N64's C-up/C-down while walking; the game thread + * consumes it once per tick (portLookAheadManualPitch). */ +static SDL_atomic_t s_manualPitch; +static void noteManualPitch(void) { SDL_AtomicSet(&s_manualPitch, 1); } +int portLookAheadManualPitch(void) { return SDL_AtomicSet(&s_manualPitch, 0); } /* D645: Original scheme -- F10 "Invert look" mirrors the game's own * "Look up/down" (watchsettings.c keeps the two in sync both ways). */ static int padLookInvertY = 0; /* Input.PadLookInvertY: 1 = invert the look stick's Y (right stick in SOLITARE roles, left stick in HONEY roles -- #145) */ @@ -2673,6 +2680,8 @@ static unsigned inputComputePadSlot(int idx, signed char *stick_x, signed char * double dyLook = edy * invert; /* >0 => look down */ if (!menuMode && (fabs(edx) > 0.01 || fabs(dyLook) > 0.01)) s_aimDevMouse = 1; /* D337: mouse is the active aim device */ + if (!menuMode && fabs(dyLook) > 0.01) + noteManualPitch(); /* D194(b): gameplay-look-only dt normalization -- see the * MOUSE_DT_REF comment above. Computed unconditionally (so the @@ -3007,6 +3016,7 @@ static unsigned inputComputePadSlot(int idx, signed char *stick_x, signed char * rys = (int)lround(padSmSY[idx]); } if (padLookInvertY) rys = -rys; + if (rys) noteManualPitch(); if (idx == 0) { s_recPadDX = rxs; s_recPadDY = rys; s_recPadDirect = 0; } if (aimModeGet() == AIMMODE_CENTRED && !(idx == 0 && s_replayActive) && padDirectCompute(rxs, rys)) { diff --git a/src/game/bondview2.c b/src/game/bondview2.c index c0a4e2f4..3b8d7774 100644 --- a/src/game/bondview2.c +++ b/src/game/bondview2.c @@ -5939,6 +5939,52 @@ void bondviewProcessInput(s8 stick_x, s8 stick_y, u16 buttons, u16 oldbuttons) } } +#ifdef PORT + /* Look ahead in the Modern scheme. The port runs the stick-look style + * (1.2/1.4: left stick walks through digital C-steps, right stick or + * mouse pitches the view), where the N64 turns look ahead off and its + * trigger (analog walk past 60) never fires anyway. Enable it there, + * let walking forward/back stand in for the analog walk, and make a + * manual pitch release the centring until the walk stops, like + * C-up/C-down while walking with the 1.1 analog stick. */ + { + extern int inputControlScheme(void); + extern int portLookAheadManualPitch(void); + s32 manualpitch = portLookAheadManualPitch(); + + if (inputControlScheme() == 0) + { + const s32 type = cur_player_get_control_type(); + + /* Stick-look styles: the stick channel is the look, not a walk */ + if ((type == CONTROLLER_CONFIG_SOLITARE) || (type == CONTROLLER_CONFIG_GOODNIGHT)) + { + moveData.canLookAhead = !g_CurrentPlayer->insightaimmode; + moveData.disableLookAhead = 0; + + /* The look stick in N64 aim mode reaches the game as natural pitch */ + if (moveData.canNaturalPitch && (moveData.analogPitch != 0)) + { + manualpitch = TRUE; + } + moveData.analogWalk = moveData.digitalStepForward ? 70 : (moveData.digitalStepBack ? -70 : 0); + } + + /* As the N64 does for C-up/C-down (speedVertaDown/Up below) */ + if (manualpitch) + { + g_CurrentPlayer->docentreupdown = FALSE; + g_CurrentPlayer->automovecentre = FALSE; + + if (moveData.canLookAhead && ((moveData.analogWalk > 60) || (moveData.analogWalk < -60))) + { + g_CurrentPlayer->movecentrerelease = TRUE; + } + } + } + } +#endif + if ((g_CurrentPlayer->movecentrerelease) && (moveData.analogWalk < 40) && (moveData.analogWalk > -40)) { g_CurrentPlayer->movecentrerelease = FALSE;