Add fake high-resolution turning setting (#1691)

This commit is contained in:
ceski 2024-05-22 06:28:43 -07:00 committed by GitHub
parent 9011fbcfd8
commit 62ddc5c1b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 120 additions and 60 deletions

View File

@ -2738,7 +2738,7 @@ void D_DoomMain(void)
D_CheckNetGame(); D_CheckNetGame();
G_UpdateSideMove(); G_UpdateSideMove();
G_UpdateCarryAngle(); G_UpdateAngleFunctions();
I_UpdateAccelerateMouse(); I_UpdateAccelerateMouse();
MN_ResetTimeScale(); MN_ResetTimeScale();

View File

@ -25,6 +25,7 @@
// animation states (closely tied to the sprites // animation states (closely tied to the sprites
// used to represent them, unfortunately). // used to represent them, unfortunately).
#include "p_pspr.h" #include "p_pspr.h"
#include "tables.h"
// In addition, the player is just a special // In addition, the player is just a special
// case of the generic moving object/actor. // case of the generic moving object/actor.
@ -210,6 +211,9 @@ typedef struct player_s
// DSDA UV Max category requirements // DSDA UV Max category requirements
int maxkilldiscount; int maxkilldiscount;
// Local angle for blending per-frame and per-tic turning.
angle_t ticangle, oldticangle;
} player_t; } player_t;

View File

@ -37,6 +37,7 @@ typedef struct ticcmd_s
byte buttons; byte buttons;
int pitch; int pitch;
short ticangleturn; // Local angle delta for composite input only.
} ticcmd_t; } ticcmd_t;
#endif #endif

View File

@ -293,6 +293,9 @@ extern boolean lowres_turn;
// Config key for low resolution turning. // Config key for low resolution turning.
extern boolean shorttics; extern boolean shorttics;
// Fake longtics when using shorttics.
extern boolean fake_longtics;
// cph's doom 1.91 longtics hack // cph's doom 1.91 longtics hack
extern boolean longtics; extern boolean longtics;

View File

@ -142,6 +142,7 @@ int max_kill_requirement; // DSDA UV Max category requirements
int totalleveltimes; // [FG] total time for all completed levels int totalleveltimes; // [FG] total time for all completed levels
boolean demorecording; boolean demorecording;
boolean longtics; // cph's doom 1.91 longtics hack 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 shorttics; // Config key for low resolution turning.
boolean lowres_turn; // low resolution turning for longtics boolean lowres_turn; // low resolution turning for longtics
boolean demoplayback; boolean demoplayback;
@ -213,7 +214,6 @@ typedef struct carry_s
double pitch; double pitch;
double side; double side;
double vert; double vert;
short lowres;
} carry_t; } carry_t;
static carry_t prevcarry; static carry_t prevcarry;
@ -444,8 +444,8 @@ static double CalcControllerAngle(void)
static double CalcControllerPitch(void) static double CalcControllerPitch(void)
{ {
const double pitch = angleturn[1] * axes[AXIS_LOOK]; return (angleturn[1] * axes[AXIS_LOOK] * direction[joy_invert_look]
return (pitch * FRACUNIT * direction[joy_invert_look]); * FRACUNIT);
} }
static int CarryError(double value, const double *prevcarry, double *carry) 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; return actual;
} }
static short CarryAngle_Full(double angle) static short CarryAngleTic_Full(double angle)
{ {
return CarryError(angle, &prevcarry.angle, &carry.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; const short fullres = CarryAngleTic_Full(angle);
// Round to nearest 256 for single byte turning. From Chocolate Doom. localview.angle = fullres << FRACBITS;
const short actual = (desired + 128) & 0xFF00; return fullres;
carry.lowres = desired - actual;
return actual;
} }
static short (*CarryAngle)(double angle) = CarryAngle_Full; static short CarryAngle_FakeLongTics(double angle)
void G_UpdateCarryAngle(void)
{ {
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) 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) static int CarryMouseVert(double vert)
@ -505,14 +554,11 @@ static double CalcMouseAngle(int mousex)
static double CalcMousePitch(int mousey) static double CalcMousePitch(int mousey)
{ {
double pitch;
if (!mouse_sensitivity_y_look) if (!mouse_sensitivity_y_look)
return 0.0; return 0.0;
pitch = I_AccelerateMouse(mousey) * (mouse_sensitivity_y_look + 5) * 8 / 10; return (I_AccelerateMouse(mousey) * (mouse_sensitivity_y_look + 5) * 8 / 10
* direction[mouse_y_invert] * FRACUNIT);
return pitch * FRACUNIT * direction[mouse_y_invert];
} }
static double CalcMouseSide(int mousex) static double CalcMouseSide(int mousex)
@ -520,8 +566,7 @@ static double CalcMouseSide(int mousex)
if (!mouse_sensitivity_strafe) if (!mouse_sensitivity_strafe)
return 0.0; return 0.0;
return (I_AccelerateMouse(mousex) * return (I_AccelerateMouse(mousex) * (mouse_sensitivity_strafe + 5) * 2 / 10);
(mouse_sensitivity_strafe + 5) * 2 / 10);
} }
static double CalcMouseVert(int mousey) static double CalcMouseVert(int mousey)
@ -586,7 +631,7 @@ static void ApplyQuickstartCache(ticcmd_t *cmd, boolean strafe)
result += angleturn_cache[i]; result += angleturn_cache[i];
} }
cmd->angleturn = CarryAngle(result); cmd->angleturn = CarryAngleTic(result);
localview.rawangle = cmd->angleturn; localview.rawangle = cmd->angleturn;
} }
@ -623,7 +668,6 @@ void G_PrepTiccmd(void)
{ {
localview.rawangle -= CalcControllerAngle() * deltatics; localview.rawangle -= CalcControllerAngle() * deltatics;
cmd->angleturn = CarryAngle(localview.rawangle); cmd->angleturn = CarryAngle(localview.rawangle);
localview.angle = cmd->angleturn << 16;
axes[AXIS_TURN] = 0.0f; axes[AXIS_TURN] = 0.0f;
} }
@ -631,7 +675,6 @@ void G_PrepTiccmd(void)
{ {
localview.rawpitch -= CalcControllerPitch() * deltatics; localview.rawpitch -= CalcControllerPitch() * deltatics;
cmd->pitch = CarryPitch(localview.rawpitch); cmd->pitch = CarryPitch(localview.rawpitch);
localview.pitch = cmd->pitch;
axes[AXIS_LOOK] = 0.0f; axes[AXIS_LOOK] = 0.0f;
} }
} }
@ -642,7 +685,6 @@ void G_PrepTiccmd(void)
{ {
localview.rawangle -= CalcMouseAngle(mousex); localview.rawangle -= CalcMouseAngle(mousex);
cmd->angleturn = CarryAngle(localview.rawangle); cmd->angleturn = CarryAngle(localview.rawangle);
localview.angle = cmd->angleturn << 16;
mousex = 0; mousex = 0;
} }
@ -650,7 +692,6 @@ void G_PrepTiccmd(void)
{ {
localview.rawpitch += CalcMousePitch(mousey); localview.rawpitch += CalcMousePitch(mousey);
cmd->pitch = CarryPitch(localview.rawpitch); cmd->pitch = CarryPitch(localview.rawpitch);
localview.pitch = cmd->pitch;
mousey = 0; mousey = 0;
} }
} }
@ -778,8 +819,8 @@ void G_BuildTiccmd(ticcmd_t* cmd)
if (angle) if (angle)
{ {
const short old_angleturn = cmd->angleturn; const short old_angleturn = cmd->angleturn;
cmd->angleturn = CarryAngle(localview.rawangle + angle); cmd->angleturn = CarryAngleTic(localview.rawangle + angle);
localview.ticangleturn = cmd->angleturn - old_angleturn; cmd->ticangleturn = cmd->angleturn - old_angleturn;
} }
if (forward > MAXPLMOVE) if (forward > MAXPLMOVE)
@ -797,10 +838,7 @@ void G_BuildTiccmd(ticcmd_t* cmd)
ClearQuickstartTic(); ClearQuickstartTic();
I_ResetControllerAxes(); I_ResetControllerAxes();
mousex = mousey = 0; mousex = mousey = 0;
localview.angle = 0; UpdateLocalView();
localview.pitch = 0;
localview.rawangle = 0.0;
localview.rawpitch = 0.0;
prevcarry = carry; prevcarry = carry;
// Buttons // Buttons
@ -1625,6 +1663,7 @@ static void G_PlayerFinishLevel(int player)
p->centering = false; p->centering = false;
p->slope = 0; p->slope = 0;
p->recoilpitch = p->oldrecoilpitch = 0; p->recoilpitch = p->oldrecoilpitch = 0;
p->ticangle = p->oldticangle = 0;
} }
// [crispy] format time for level statistics // [crispy] format time for level statistics
@ -4596,8 +4635,12 @@ void G_BindGameInputVariables(void)
void G_BindGameVariables(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_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, BIND_NUM_GENERAL(default_skill, 3, 1, 5,
"Default skill level (1 = ITYTD; 2 = HNTR; 3 = HMP; 4 = UV; 5 = NM)"); "Default skill level (1 = ITYTD; 2 = HNTR; 3 = HMP; 4 = UV; 5 = NM)");
BIND_NUM_GENERAL(realtic_clock_rate, 100, 10, 1000, BIND_NUM_GENERAL(realtic_clock_rate, 100, 10, 1000,

View File

@ -54,7 +54,7 @@ void G_WorldDone(void);
void G_Ticker(void); void G_Ticker(void);
void G_ScreenShot(void); void G_ScreenShot(void);
void G_UpdateSideMove(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 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_SaveGameName(int); // killough 3/22/98: sets savegame filename
char *G_MBFSaveGameName(int); // MBF savegame filename char *G_MBFSaveGameName(int); // MBF savegame filename

View File

@ -2359,6 +2359,8 @@ void MN_UpdateAdvancedSoundItems(boolean toggle)
void MN_UpdateFpsLimitItem(void) void MN_UpdateFpsLimitItem(void)
{ {
DisableItem(!uncapped, gen_settings1, "fpslimit"); DisableItem(!uncapped, gen_settings1, "fpslimit");
G_ClearInput();
G_UpdateAngleFunctions();
} }
void MN_DisableVoxelsRenderingItem(void) void MN_DisableVoxelsRenderingItem(void)

View File

@ -649,6 +649,18 @@ void A_GunFlash(player_t *player, pspdef_t *psp)
// WEAPON ATTACKS // 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 // A_Punch
// //
@ -685,8 +697,10 @@ void A_Punch(player_t *player, pspdef_t *psp)
// turn to face target // turn to face target
SavePlayerAngle(player);
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->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, angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y); linetarget->x, linetarget->y);
SavePlayerAngle(player);
if (angle - player->mo->angle > ANG180) if (angle - player->mo->angle > ANG180)
if ((signed int) (angle - player->mo->angle) < -ANG90/20) if ((signed int) (angle - player->mo->angle) < -ANG90/20)
player->mo->angle = angle + ANG90/21; 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; player->mo->angle = angle - ANG90/21;
else else
player->mo->angle += ANG90/20; player->mo->angle += ANG90/20;
AddToTicAngle(player);
player->mo->flags |= MF_JUSTATTACKED; player->mo->flags |= MF_JUSTATTACKED;
} }
@ -1302,7 +1318,9 @@ void A_WeaponMeleeAttack(player_t *player, pspdef_t *psp)
S_StartSound(player->mo, hitsound); S_StartSound(player->mo, hitsound);
// turn to face target // turn to face target
SavePlayerAngle(player);
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y); player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y);
AddToTicAngle(player);
} }
// //

View File

@ -215,12 +215,7 @@ void P_MovePlayer (player_t* player)
mo->angle += cmd->angleturn << 16; mo->angle += cmd->angleturn << 16;
onground = mo->z <= mo->floorz; onground = mo->z <= mo->floorz;
player->ticangle += cmd->ticangleturn << FRACBITS;
if (player == &players[consoleplayer])
{
localview.ticangle += localview.ticangleturn << 16;
localview.ticangleturn = 0;
}
// killough 10/98: // killough 10/98:
// //
@ -377,11 +372,7 @@ void P_PlayerThink (player_t* player)
player->oldviewz = player->viewz; player->oldviewz = player->viewz;
player->oldpitch = player->pitch; player->oldpitch = player->pitch;
player->oldrecoilpitch = player->recoilpitch; player->oldrecoilpitch = player->recoilpitch;
player->oldticangle = player->ticangle;
if (player == &players[consoleplayer])
{
localview.oldticangle = localview.ticangle;
}
// killough 2/8/98, 3/21/98: // killough 2/8/98, 3/21/98:
// (this code is necessary despite questions raised elsewhere in a comment) // (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) if (player->mo->flags & MF_JUSTATTACKED)
{ {
cmd->angleturn = 0; cmd->angleturn = 0;
cmd->ticangleturn = 0;
cmd->forwardmove = 0xc800/512; cmd->forwardmove = 0xc800/512;
cmd->sidemove = 0; cmd->sidemove = 0;
player->mo->flags &= ~MF_JUSTATTACKED; player->mo->flags &= ~MF_JUSTATTACKED;

View File

@ -723,6 +723,7 @@ void R_SetupFrame (player_t *player)
{ {
int i, cm; int i, cm;
fixed_t pitch; fixed_t pitch;
const boolean use_localview = CheckLocalView(player);
viewplayer = player; viewplayer = player;
// [AM] Interpolate the player camera if the feature is enabled. // [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 // Don't interpolate during a paused state
leveltime > oldleveltime) 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. // Interpolate player camera from their old position to their current one.
viewx = LerpFixed(player->mo->oldx, player->mo->x); viewx = LerpFixed(player->mo->oldx, player->mo->x);
viewy = LerpFixed(player->mo->oldy, player->mo->y); viewy = LerpFixed(player->mo->oldy, player->mo->y);
@ -747,8 +744,8 @@ void R_SetupFrame (player_t *player)
if (use_localview) if (use_localview)
{ {
viewangle = (player->mo->angle + localview.angle - localview.ticangle + viewangle = (player->mo->angle + localview.angle - player->ticangle +
LerpAngle(localview.oldticangle, localview.ticangle)); LerpAngle(player->oldticangle, player->ticangle));
} }
else else
{ {
@ -776,6 +773,11 @@ void R_SetupFrame (player_t *player)
viewangle = player->mo->angle; viewangle = player->mo->angle;
// [crispy] pitch is actual lookdir and weapon pitch // [crispy] pitch is actual lookdir and weapon pitch
pitch = player->pitch + player->recoilpitch; pitch = player->pitch + player->recoilpitch;
if (use_localview && lowres_turn && fake_longtics)
{
viewangle += localview.angle;
}
} }
if (pitch != viewpitch) if (pitch != viewpitch)
@ -994,9 +996,6 @@ void R_BindRenderVariables(void)
BIND_BOOL(draw_nearby_sprites, true, BIND_BOOL(draw_nearby_sprites, true,
"Draw sprites overlapping into visible sectors"); "Draw sprites overlapping into visible sectors");
BIND_BOOL(raw_input, true,
"Raw gamepad/mouse input for turning/looking (0 = Interpolate; 1 = Raw)");
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -91,13 +91,11 @@ extern side_t *sides;
typedef struct localview_s typedef struct localview_s
{ {
angle_t oldticangle;
angle_t ticangle;
short ticangleturn;
double rawangle; double rawangle;
double rawpitch; double rawpitch;
angle_t angle; angle_t angle;
int pitch; fixed_t pitch;
short angleoffset;
} localview_t; } localview_t;
// //