From 62ddc5c1b84f90db454e69edd385fc790da35846 Mon Sep 17 00:00:00 2001 From: ceski <56656010+ceski-1@users.noreply.github.com> Date: Wed, 22 May 2024 06:28:43 -0700 Subject: [PATCH] Add fake high-resolution turning setting (#1691) --- src/d_main.c | 2 +- src/d_player.h | 4 ++ src/d_ticcmd.h | 1 + src/doomstat.h | 3 ++ src/g_game.c | 111 ++++++++++++++++++++++++++++++++++--------------- src/g_game.h | 2 +- src/mn_setup.c | 2 + src/p_pspr.c | 18 ++++++++ src/p_user.c | 14 ++----- src/r_main.c | 17 ++++---- src/r_state.h | 6 +-- 11 files changed, 120 insertions(+), 60 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index ef826e80..d64eb841 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2738,7 +2738,7 @@ void D_DoomMain(void) D_CheckNetGame(); G_UpdateSideMove(); - G_UpdateCarryAngle(); + G_UpdateAngleFunctions(); I_UpdateAccelerateMouse(); MN_ResetTimeScale(); diff --git a/src/d_player.h b/src/d_player.h index 570048df..af268cf8 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -25,6 +25,7 @@ // animation states (closely tied to the sprites // used to represent them, unfortunately). #include "p_pspr.h" +#include "tables.h" // In addition, the player is just a special // case of the generic moving object/actor. @@ -210,6 +211,9 @@ typedef struct player_s // DSDA UV Max category requirements int maxkilldiscount; + // Local angle for blending per-frame and per-tic turning. + angle_t ticangle, oldticangle; + } player_t; diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index e108184a..7ab85313 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -37,6 +37,7 @@ typedef struct ticcmd_s byte buttons; int pitch; + short ticangleturn; // Local angle delta for composite input only. } ticcmd_t; #endif diff --git a/src/doomstat.h b/src/doomstat.h index dd312044..6d595068 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -293,6 +293,9 @@ extern boolean lowres_turn; // Config key for low resolution turning. extern boolean shorttics; +// Fake longtics when using shorttics. +extern boolean fake_longtics; + // cph's doom 1.91 longtics hack extern boolean longtics; diff --git a/src/g_game.c b/src/g_game.c index 2f6c5257..347e1d6a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -142,6 +142,7 @@ int max_kill_requirement; // DSDA UV Max category requirements int totalleveltimes; // [FG] total time for all completed levels boolean demorecording; boolean longtics; // cph's doom 1.91 longtics hack +boolean fake_longtics; // Fake longtics when using shorttics. boolean shorttics; // Config key for low resolution turning. boolean lowres_turn; // low resolution turning for longtics boolean demoplayback; @@ -213,7 +214,6 @@ typedef struct carry_s double pitch; double side; double vert; - short lowres; } carry_t; static carry_t prevcarry; @@ -444,8 +444,8 @@ static double CalcControllerAngle(void) static double CalcControllerPitch(void) { - const double pitch = angleturn[1] * axes[AXIS_LOOK]; - return (pitch * FRACUNIT * direction[joy_invert_look]); + return (angleturn[1] * axes[AXIS_LOOK] * direction[joy_invert_look] + * FRACUNIT); } static int CarryError(double value, const double *prevcarry, double *carry) @@ -456,30 +456,79 @@ static int CarryError(double value, const double *prevcarry, double *carry) return actual; } -static short CarryAngle_Full(double angle) +static short CarryAngleTic_Full(double angle) { return CarryError(angle, &prevcarry.angle, &carry.angle); } -static short CarryAngle_LowRes(double angle) +static short CarryAngle_Full(double angle) { - const short desired = CarryAngle_Full(angle) + prevcarry.lowres; - // Round to nearest 256 for single byte turning. From Chocolate Doom. - const short actual = (desired + 128) & 0xFF00; - carry.lowres = desired - actual; - return actual; + const short fullres = CarryAngleTic_Full(angle); + localview.angle = fullres << FRACBITS; + return fullres; } -static short (*CarryAngle)(double angle) = CarryAngle_Full; - -void G_UpdateCarryAngle(void) +static short CarryAngle_FakeLongTics(double angle) { - CarryAngle = lowres_turn ? CarryAngle_LowRes : CarryAngle_Full; + return (localview.angleoffset = (CarryAngle_Full(angle) + 128) & 0xFF00); +} + +static short CarryAngleTic_LowRes(double angle) +{ + const double fullres = angle + prevcarry.angle; + const short lowres = ((short)lround(fullres) + 128) & 0xFF00; + carry.angle = fullres - lowres; + return lowres; +} + +static short CarryAngle_LowRes(double angle) +{ + const short lowres = CarryAngleTic_LowRes(angle); + localview.angle = lowres << FRACBITS; + return lowres; +} + +static void UpdateLocalView_Zero(void) +{ + memset(&localview, 0, sizeof(localview)); +} + +static void UpdateLocalView_FakeLongTics(void) +{ + localview.angle -= localview.angleoffset << FRACBITS; + localview.rawangle -= localview.angleoffset; + localview.angleoffset = 0; + localview.pitch = 0; + localview.rawpitch = 0.0; +} + +static short (*CarryAngleTic)(double angle); +static short (*CarryAngle)(double angle); +static void (*UpdateLocalView)(void); + +void G_UpdateAngleFunctions(void) +{ + CarryAngleTic = lowres_turn ? CarryAngleTic_LowRes : CarryAngleTic_Full; + CarryAngle = CarryAngleTic; + UpdateLocalView = UpdateLocalView_Zero; + + if (raw_input && (!netgame || solonet)) + { + if (lowres_turn && fake_longtics) + { + CarryAngle = CarryAngle_FakeLongTics; + UpdateLocalView = UpdateLocalView_FakeLongTics; + } + else if (uncapped) + { + CarryAngle = lowres_turn ? CarryAngle_LowRes : CarryAngle_Full; + } + } } static int CarryPitch(double pitch) { - return CarryError(pitch, &prevcarry.pitch, &carry.pitch); + return (localview.pitch = CarryError(pitch, &prevcarry.pitch, &carry.pitch)); } static int CarryMouseVert(double vert) @@ -505,14 +554,11 @@ static double CalcMouseAngle(int mousex) static double CalcMousePitch(int mousey) { - double pitch; - if (!mouse_sensitivity_y_look) return 0.0; - pitch = I_AccelerateMouse(mousey) * (mouse_sensitivity_y_look + 5) * 8 / 10; - - return pitch * FRACUNIT * direction[mouse_y_invert]; + return (I_AccelerateMouse(mousey) * (mouse_sensitivity_y_look + 5) * 8 / 10 + * direction[mouse_y_invert] * FRACUNIT); } static double CalcMouseSide(int mousex) @@ -520,8 +566,7 @@ static double CalcMouseSide(int mousex) if (!mouse_sensitivity_strafe) return 0.0; - return (I_AccelerateMouse(mousex) * - (mouse_sensitivity_strafe + 5) * 2 / 10); + return (I_AccelerateMouse(mousex) * (mouse_sensitivity_strafe + 5) * 2 / 10); } static double CalcMouseVert(int mousey) @@ -586,7 +631,7 @@ static void ApplyQuickstartCache(ticcmd_t *cmd, boolean strafe) result += angleturn_cache[i]; } - cmd->angleturn = CarryAngle(result); + cmd->angleturn = CarryAngleTic(result); localview.rawangle = cmd->angleturn; } @@ -623,7 +668,6 @@ void G_PrepTiccmd(void) { localview.rawangle -= CalcControllerAngle() * deltatics; cmd->angleturn = CarryAngle(localview.rawangle); - localview.angle = cmd->angleturn << 16; axes[AXIS_TURN] = 0.0f; } @@ -631,7 +675,6 @@ void G_PrepTiccmd(void) { localview.rawpitch -= CalcControllerPitch() * deltatics; cmd->pitch = CarryPitch(localview.rawpitch); - localview.pitch = cmd->pitch; axes[AXIS_LOOK] = 0.0f; } } @@ -642,7 +685,6 @@ void G_PrepTiccmd(void) { localview.rawangle -= CalcMouseAngle(mousex); cmd->angleturn = CarryAngle(localview.rawangle); - localview.angle = cmd->angleturn << 16; mousex = 0; } @@ -650,7 +692,6 @@ void G_PrepTiccmd(void) { localview.rawpitch += CalcMousePitch(mousey); cmd->pitch = CarryPitch(localview.rawpitch); - localview.pitch = cmd->pitch; mousey = 0; } } @@ -778,8 +819,8 @@ void G_BuildTiccmd(ticcmd_t* cmd) if (angle) { const short old_angleturn = cmd->angleturn; - cmd->angleturn = CarryAngle(localview.rawangle + angle); - localview.ticangleturn = cmd->angleturn - old_angleturn; + cmd->angleturn = CarryAngleTic(localview.rawangle + angle); + cmd->ticangleturn = cmd->angleturn - old_angleturn; } if (forward > MAXPLMOVE) @@ -797,10 +838,7 @@ void G_BuildTiccmd(ticcmd_t* cmd) ClearQuickstartTic(); I_ResetControllerAxes(); mousex = mousey = 0; - localview.angle = 0; - localview.pitch = 0; - localview.rawangle = 0.0; - localview.rawpitch = 0.0; + UpdateLocalView(); prevcarry = carry; // Buttons @@ -1625,6 +1663,7 @@ static void G_PlayerFinishLevel(int player) p->centering = false; p->slope = 0; p->recoilpitch = p->oldrecoilpitch = 0; + p->ticangle = p->oldticangle = 0; } // [crispy] format time for level statistics @@ -4596,8 +4635,12 @@ void G_BindGameInputVariables(void) void G_BindGameVariables(void) { + BIND_BOOL(raw_input, true, + "Raw gamepad/mouse input for turning/looking (0 = Interpolate; 1 = Raw)"); + BIND_BOOL(fake_longtics, true, + "Fake high-resolution turning when using low-resolution turning"); + BIND_BOOL(shorttics, false, "Always use low-resolution turning"); BIND_NUM(quickstart_cache_tics, 0, 0, TICRATE, "Quickstart cache tics"); - BIND_BOOL(shorttics, false, "Low-resolution turning"); BIND_NUM_GENERAL(default_skill, 3, 1, 5, "Default skill level (1 = ITYTD; 2 = HNTR; 3 = HMP; 4 = UV; 5 = NM)"); BIND_NUM_GENERAL(realtic_clock_rate, 100, 10, 1000, diff --git a/src/g_game.h b/src/g_game.h index ea4f3900..cabef24b 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -54,7 +54,7 @@ void G_WorldDone(void); void G_Ticker(void); void G_ScreenShot(void); void G_UpdateSideMove(void); -void G_UpdateCarryAngle(void); +void G_UpdateAngleFunctions(void); void G_ReloadDefaults(boolean keep_demover); // killough 3/1/98: loads game defaults char *G_SaveGameName(int); // killough 3/22/98: sets savegame filename char *G_MBFSaveGameName(int); // MBF savegame filename diff --git a/src/mn_setup.c b/src/mn_setup.c index 29442127..71b17bf1 100644 --- a/src/mn_setup.c +++ b/src/mn_setup.c @@ -2359,6 +2359,8 @@ void MN_UpdateAdvancedSoundItems(boolean toggle) void MN_UpdateFpsLimitItem(void) { DisableItem(!uncapped, gen_settings1, "fpslimit"); + G_ClearInput(); + G_UpdateAngleFunctions(); } void MN_DisableVoxelsRenderingItem(void) diff --git a/src/p_pspr.c b/src/p_pspr.c index 585bd2e8..d5fe0636 100644 --- a/src/p_pspr.c +++ b/src/p_pspr.c @@ -649,6 +649,18 @@ void A_GunFlash(player_t *player, pspdef_t *psp) // WEAPON ATTACKS // +static angle_t saved_angle; + +static void SavePlayerAngle(player_t *player) +{ + saved_angle = player->mo->angle; +} + +static void AddToTicAngle(player_t *player) +{ + player->ticangle += player->mo->angle - saved_angle; +} + // // A_Punch // @@ -685,8 +697,10 @@ void A_Punch(player_t *player, pspdef_t *psp) // turn to face target + SavePlayerAngle(player); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); + AddToTicAngle(player); } // @@ -729,6 +743,7 @@ void A_Saw(player_t *player, pspdef_t *psp) angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); + SavePlayerAngle(player); if (angle - player->mo->angle > ANG180) if ((signed int) (angle - player->mo->angle) < -ANG90/20) player->mo->angle = angle + ANG90/21; @@ -739,6 +754,7 @@ void A_Saw(player_t *player, pspdef_t *psp) player->mo->angle = angle - ANG90/21; else player->mo->angle += ANG90/20; + AddToTicAngle(player); player->mo->flags |= MF_JUSTATTACKED; } @@ -1302,7 +1318,9 @@ void A_WeaponMeleeAttack(player_t *player, pspdef_t *psp) S_StartSound(player->mo, hitsound); // turn to face target + SavePlayerAngle(player); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); + AddToTicAngle(player); } // diff --git a/src/p_user.c b/src/p_user.c index 4ac516ab..3d3b4c40 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -215,12 +215,7 @@ void P_MovePlayer (player_t* player) mo->angle += cmd->angleturn << 16; onground = mo->z <= mo->floorz; - - if (player == &players[consoleplayer]) - { - localview.ticangle += localview.ticangleturn << 16; - localview.ticangleturn = 0; - } + player->ticangle += cmd->ticangleturn << FRACBITS; // killough 10/98: // @@ -377,11 +372,7 @@ void P_PlayerThink (player_t* player) player->oldviewz = player->viewz; player->oldpitch = player->pitch; player->oldrecoilpitch = player->recoilpitch; - - if (player == &players[consoleplayer]) - { - localview.oldticangle = localview.ticangle; - } + player->oldticangle = player->ticangle; // killough 2/8/98, 3/21/98: // (this code is necessary despite questions raised elsewhere in a comment) @@ -397,6 +388,7 @@ void P_PlayerThink (player_t* player) if (player->mo->flags & MF_JUSTATTACKED) { cmd->angleturn = 0; + cmd->ticangleturn = 0; cmd->forwardmove = 0xc800/512; cmd->sidemove = 0; player->mo->flags &= ~MF_JUSTATTACKED; diff --git a/src/r_main.c b/src/r_main.c index c6ba6a55..cb2bfff4 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -723,6 +723,7 @@ void R_SetupFrame (player_t *player) { int i, cm; fixed_t pitch; + const boolean use_localview = CheckLocalView(player); viewplayer = player; // [AM] Interpolate the player camera if the feature is enabled. @@ -736,10 +737,6 @@ void R_SetupFrame (player_t *player) // Don't interpolate during a paused state leveltime > oldleveltime) { - // Use localview unless the player or game is in an invalid state, in which - // case fall back to interpolation. - const boolean use_localview = CheckLocalView(player); - // Interpolate player camera from their old position to their current one. viewx = LerpFixed(player->mo->oldx, player->mo->x); viewy = LerpFixed(player->mo->oldy, player->mo->y); @@ -747,8 +744,8 @@ void R_SetupFrame (player_t *player) if (use_localview) { - viewangle = (player->mo->angle + localview.angle - localview.ticangle + - LerpAngle(localview.oldticangle, localview.ticangle)); + viewangle = (player->mo->angle + localview.angle - player->ticangle + + LerpAngle(player->oldticangle, player->ticangle)); } else { @@ -776,6 +773,11 @@ void R_SetupFrame (player_t *player) viewangle = player->mo->angle; // [crispy] pitch is actual lookdir and weapon pitch pitch = player->pitch + player->recoilpitch; + + if (use_localview && lowres_turn && fake_longtics) + { + viewangle += localview.angle; + } } if (pitch != viewpitch) @@ -994,9 +996,6 @@ void R_BindRenderVariables(void) BIND_BOOL(draw_nearby_sprites, true, "Draw sprites overlapping into visible sectors"); - - BIND_BOOL(raw_input, true, - "Raw gamepad/mouse input for turning/looking (0 = Interpolate; 1 = Raw)"); } //---------------------------------------------------------------------------- diff --git a/src/r_state.h b/src/r_state.h index 50728da4..1dc7991c 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -91,13 +91,11 @@ extern side_t *sides; typedef struct localview_s { - angle_t oldticangle; - angle_t ticangle; - short ticangleturn; double rawangle; double rawpitch; angle_t angle; - int pitch; + fixed_t pitch; + short angleoffset; } localview_t; //