Refactor game input utility functions (#1705)

This commit is contained in:
ceski 2024-05-25 06:35:15 -07:00 committed by GitHub
parent 46bc8de658
commit 045b3a2797
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 593 additions and 438 deletions

View File

@ -28,6 +28,7 @@ set(WOOF_SOURCES
f_wipe.c f_wipe.h
font.h
g_game.c g_game.h
g_input.c g_input.h
hu_command.c hu_command.h
hu_lib.c hu_lib.h
hu_obituary.c hu_obituary.h

View File

@ -223,39 +223,13 @@ void D_ProcessEvents (void)
}
}
static boolean input_ready;
void D_UpdateDeltaTics(void)
{
if (uncapped && raw_input)
{
static uint64_t last_time;
const uint64_t current_time = I_GetTimeUS();
if (input_ready)
{
const uint64_t delta_time = current_time - last_time;
deltatics = (double)delta_time * TICRATE / 1000000.0;
deltatics = BETWEEN(0.0, 1.0, deltatics);
}
else
{
deltatics = 0.0;
}
last_time = current_time;
}
else
{
deltatics = 1.0;
}
}
//
// D_Display
// draw current display, possibly wiping it from the previous
//
boolean input_ready;
// wipegamestate can be set to -1 to force a wipe on the next draw
gamestate_t wipegamestate = GS_DEMOSCREEN;
static int screen_melt = wipe_Melt;
@ -2504,7 +2478,7 @@ void D_DoomMain(void)
G_UpdateSideMove();
G_UpdateAngleFunctions();
I_UpdateAccelerateMouse();
G_UpdateAccelerateMouse();
MN_ResetTimeScale();

View File

@ -46,7 +46,7 @@ boolean D_CheckEndDoom(void);
// Called by IO functions when input is detected.
void D_PostEvent(struct event_s *ev);
void D_UpdateDeltaTics(void);
extern boolean input_ready;
void D_BindMiscVariables(void);

View File

@ -153,7 +153,7 @@ wbstartstruct_t wminfo; // parms for world map / intermission
boolean haswolflevels = false;// jff 4/18/98 wolf levels present
byte *savebuffer;
boolean autorun = false; // always running? // phares
static boolean autostrafe50;
boolean autostrafe50;
boolean novert = false;
boolean mouselook = false;
boolean padlook = false;
@ -178,14 +178,16 @@ static ticcmd_t* last_cmd = NULL;
int key_escape = KEY_ESCAPE; // phares 4/13/98
int key_help = KEY_F1; // phares 4/13/98
static int mouse_sensitivity;
static int mouse_sensitivity_y;
static int mouse_sensitivity_strafe; // [FG] strafe
static int mouse_sensitivity_y_look; // [FG] look
int mouse_sensitivity;
int mouse_sensitivity_y;
int mouse_sensitivity_strafe; // [FG] strafe
int mouse_sensitivity_y_look; // [FG] look
// [FG] double click acts as "use"
static boolean dclick_use;
// [FG] invert vertical axis
static boolean mouse_y_invert;
boolean mouse_y_invert;
int mouse_acceleration;
int mouse_acceleration_threshold;
#define MAXPLMOVE (forwardmove[1])
#define TURBOTHRESHOLD 0x32
@ -193,11 +195,10 @@ static boolean mouse_y_invert;
#define QUICKREVERSE 32768 // 180 degree reverse // phares
#define NUMKEYS 256
static fixed_t default_forwardmove[2] = {0x19, 0x32};
static fixed_t default_sidemove[2] = {0x18, 0x28};
fixed_t *forwardmove = default_forwardmove;
fixed_t forwardmove[2] = {0x19, 0x32};
fixed_t default_sidemove[2] = {0x18, 0x28};
fixed_t *sidemove = default_sidemove;
fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
const fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
boolean gamekeydown[NUMKEYS];
int turnheld; // for accelerative turning
@ -205,26 +206,14 @@ int turnheld; // for accelerative turning
boolean mousebuttons[NUM_MOUSE_BUTTONS];
// mouse values are used once
static int mousex;
static int mousey;
int mousex;
int mousey;
boolean dclick;
typedef struct carry_s
{
double angle;
double pitch;
double side;
double vert;
} carry_t;
static carry_t prevcarry;
static carry_t carry;
static ticcmd_t basecmd;
boolean joybuttons[NUM_CONTROLLER_BUTTONS];
static const int direction[] = { 1, -1 };
int savegameslot = -1;
char savedescription[32];
@ -391,267 +380,6 @@ static void G_DemoSkipTics(void)
}
}
static int RoundSide_Strict(double side)
{
return lround(side * 0.5) * 2; // Even values only.
}
static int RoundSide_Full(double side)
{
return lround(side);
}
static int (*RoundSide)(double side) = RoundSide_Full;
void G_UpdateSideMove(void)
{
if (strictmode || (netgame && !solonet))
{
RoundSide = RoundSide_Strict;
sidemove = default_sidemove;
}
else
{
RoundSide = RoundSide_Full;
sidemove = autostrafe50 ? default_forwardmove : default_sidemove;
}
}
static int CalcControllerForward(int speed)
{
const int forward = lroundf(forwardmove[speed] * axes[AXIS_FORWARD] *
direction[joy_invert_forward]);
return BETWEEN(-forwardmove[speed], forwardmove[speed], forward);
}
static int CalcControllerSideTurn(int speed)
{
const int side = RoundSide(forwardmove[speed] * axes[AXIS_TURN] *
direction[joy_invert_turn]);
return BETWEEN(-forwardmove[speed], forwardmove[speed], side);
}
static int CalcControllerSideStrafe(int speed)
{
const int side = RoundSide(forwardmove[speed] * axes[AXIS_STRAFE] *
direction[joy_invert_strafe]);
return BETWEEN(-sidemove[speed], sidemove[speed], side);
}
static double CalcControllerAngle(void)
{
return (angleturn[1] * axes[AXIS_TURN] * direction[joy_invert_turn]);
}
static double CalcControllerPitch(void)
{
return (angleturn[1] * axes[AXIS_LOOK] * direction[joy_invert_look]
* FRACUNIT);
}
static int CarryError(double value, const double *prevcarry, double *carry)
{
const double desired = value + *prevcarry;
const int actual = lround(desired);
*carry = desired - actual;
return actual;
}
static short CarryAngleTic_Full(double angle)
{
return CarryError(angle, &prevcarry.angle, &carry.angle);
}
static short CarryAngle_Full(double angle)
{
const short fullres = CarryAngleTic_Full(angle);
localview.angle = fullres << FRACBITS;
return fullres;
}
static short CarryAngle_FakeLongTics(double angle)
{
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 (localview.pitch = CarryError(pitch, &prevcarry.pitch, &carry.pitch));
}
static int CarryMouseVert(double vert)
{
return CarryError(vert, &prevcarry.vert, &carry.vert);
}
static int CarryMouseSide(double side)
{
const double desired = side + prevcarry.side;
const int actual = RoundSide(desired);
carry.side = desired - actual;
return actual;
}
static double CalcMouseAngle(int mousex)
{
if (!mouse_sensitivity)
return 0.0;
return (I_AccelerateMouse(mousex) * (mouse_sensitivity + 5) * 8 / 10);
}
static double CalcMousePitch(int mousey)
{
if (!mouse_sensitivity_y_look)
return 0.0;
return (I_AccelerateMouse(mousey) * (mouse_sensitivity_y_look + 5) * 8 / 10
* direction[mouse_y_invert] * FRACUNIT);
}
static double CalcMouseSide(int mousex)
{
if (!mouse_sensitivity_strafe)
return 0.0;
return (I_AccelerateMouse(mousex) * (mouse_sensitivity_strafe + 5) * 2 / 10);
}
static double CalcMouseVert(int mousey)
{
if (!mouse_sensitivity_y)
return 0.0;
return (I_AccelerateMouse(mousey) * (mouse_sensitivity_y + 5) / 10);
}
//
// ApplyQuickstartCache
// When recording a demo and the map is reloaded, cached input from a circular
// buffer can be applied prior to the screen wipe. Adapted from DSDA-Doom.
//
static int quickstart_cache_tics;
static boolean quickstart_queued;
static float axis_turn_tic;
static int mousex_tic;
static void ClearQuickstartTic(void)
{
axis_turn_tic = 0.0f;
mousex_tic = 0;
}
static void ApplyQuickstartCache(ticcmd_t *cmd, boolean strafe)
{
static float axis_turn_cache[TICRATE];
static int mousex_cache[TICRATE];
static short angleturn_cache[TICRATE];
static int index;
if (quickstart_cache_tics < 1)
{
return;
}
if (quickstart_queued)
{
axes[AXIS_TURN] = 0.0f;
mousex = 0;
if (strafe)
{
for (int i = 0; i < quickstart_cache_tics; i++)
{
axes[AXIS_TURN] += axis_turn_cache[i];
mousex += mousex_cache[i];
}
cmd->angleturn = 0;
localview.rawangle = 0.0;
}
else
{
short result = 0;
for (int i = 0; i < quickstart_cache_tics; i++)
{
result += angleturn_cache[i];
}
cmd->angleturn = CarryAngleTic(result);
localview.rawangle = cmd->angleturn;
}
memset(axis_turn_cache, 0, sizeof(axis_turn_cache));
memset(mousex_cache, 0, sizeof(mousex_cache));
memset(angleturn_cache, 0, sizeof(angleturn_cache));
index = 0;
quickstart_queued = false;
}
else
{
axis_turn_cache[index] = axis_turn_tic;
mousex_cache[index] = mousex_tic;
angleturn_cache[index] = cmd->angleturn;
index = (index + 1) % quickstart_cache_tics;
}
}
void G_PrepTiccmd(void)
{
const boolean strafe = M_InputGameActive(input_strafe);
@ -661,21 +389,18 @@ void G_PrepTiccmd(void)
if (I_UseController() && I_CalcControllerAxes())
{
D_UpdateDeltaTics();
G_UpdateDeltaTics();
axis_turn_tic = axes[AXIS_TURN];
if (axes[AXIS_TURN] && !strafe)
{
localview.rawangle -= CalcControllerAngle() * deltatics;
cmd->angleturn = CarryAngle(localview.rawangle);
cmd->angleturn = G_CalcControllerAngle();
axes[AXIS_TURN] = 0.0f;
}
if (axes[AXIS_LOOK] && padlook)
{
localview.rawpitch -= CalcControllerPitch() * deltatics;
cmd->pitch = CarryPitch(localview.rawpitch);
cmd->pitch = G_CalcControllerPitch();
axes[AXIS_LOOK] = 0.0f;
}
}
@ -684,15 +409,13 @@ void G_PrepTiccmd(void)
if (mousex && !strafe)
{
localview.rawangle -= CalcMouseAngle(mousex);
cmd->angleturn = CarryAngle(localview.rawangle);
cmd->angleturn = G_CalcMouseAngle();
mousex = 0;
}
if (mousey && mouselook)
{
localview.rawpitch += CalcMousePitch(mousey);
cmd->pitch = CarryPitch(localview.rawpitch);
cmd->pitch = G_CalcMousePitch();
mousey = 0;
}
}
@ -728,7 +451,7 @@ void G_BuildTiccmd(ticcmd_t* cmd)
memcpy(cmd, &basecmd, sizeof(*cmd));
memset(&basecmd, 0, sizeof(basecmd));
ApplyQuickstartCache(cmd, strafe);
G_ApplyQuickstartCache(cmd, strafe);
cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
@ -787,17 +510,17 @@ void G_BuildTiccmd(ticcmd_t* cmd)
{
if (axes[AXIS_TURN] && strafe && !cmd->angleturn)
{
side += CalcControllerSideTurn(speed);
side += G_CalcControllerSideTurn(speed);
}
if (axes[AXIS_STRAFE])
{
side += CalcControllerSideStrafe(speed);
side += G_CalcControllerSideStrafe(speed);
}
if (axes[AXIS_FORWARD])
{
forward -= CalcControllerForward(speed);
forward -= G_CalcControllerForward(speed);
}
}
@ -805,23 +528,19 @@ void G_BuildTiccmd(ticcmd_t* cmd)
if (mousex && strafe && !cmd->angleturn)
{
const double mouseside = CalcMouseSide(mousex);
side += CarryMouseSide(mouseside);
side += G_CalcMouseSide();
}
if (mousey && !mouselook && !novert)
{
const double mousevert = CalcMouseVert(mousey);
forward += CarryMouseVert(mousevert);
forward += G_CalcMouseVert();
}
// Update/reset
if (angle)
{
const short old_angleturn = cmd->angleturn;
cmd->angleturn = CarryAngleTic(localview.rawangle + angle);
cmd->ticangleturn = cmd->angleturn - old_angleturn;
G_UpdateTicAngleTurn(cmd, angle);
}
if (forward > MAXPLMOVE)
@ -836,11 +555,11 @@ void G_BuildTiccmd(ticcmd_t* cmd)
cmd->forwardmove = forward;
cmd->sidemove = side;
ClearQuickstartTic();
G_ClearQuickstartTic();
I_ResetControllerAxes();
mousex = mousey = 0;
UpdateLocalView();
prevcarry = carry;
G_UpdateLocalView();
G_UpdateCarry();
// Buttons
@ -991,12 +710,11 @@ void G_BuildTiccmd(ticcmd_t* cmd)
void G_ClearInput(void)
{
ClearQuickstartTic();
G_ClearQuickstartTic();
I_ResetControllerLevel();
mousex = mousey = 0;
memset(&localview, 0, sizeof(localview));
memset(&carry, 0, sizeof(carry));
memset(&prevcarry, 0, sizeof(prevcarry));
G_ClearLocalView();
G_ClearCarry();
memset(&basecmd, 0, sizeof(basecmd));
}
@ -4637,6 +4355,10 @@ void G_BindGameInputVariables(void)
"Horizontal mouse sensitivity for strafing");
BIND_NUM_GENERAL(mouse_sensitivity_y_look, 5, 0, UL,
"Vertical mouse sensitivity for looking");
BIND_NUM_GENERAL(mouse_acceleration, 10, 0, 40,
"Mouse acceleration (0 = 1.0; 40 = 5.0)");
BIND_NUM(mouse_acceleration_threshold, 10, 0, 32,
"Mouse acceleration threshold");
BIND_BOOL_GENERAL(mouse_y_invert, false, "Invert vertical mouse axis");
BIND_BOOL_GENERAL(dclick_use, true, "Double-click acts as use-button");
BIND_BOOL(novert, true, "Disable vertical mouse movement");

View File

@ -20,6 +20,7 @@
#include "doomdef.h"
#include "doomstat.h"
#include "doomtype.h"
#include "g_input.h"
#include "m_fixed.h"
struct event_s;
@ -53,8 +54,6 @@ void G_SecretExitLevel(void);
void G_WorldDone(void);
void G_Ticker(void);
void G_ScreenShot(void);
void G_UpdateSideMove(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
@ -104,12 +103,25 @@ extern int key_escape;
extern int key_enter;
extern int key_help;
extern boolean autorun; // always running? // phares
extern boolean autostrafe50;
extern boolean novert;
extern boolean mouselook;
extern boolean padlook;
extern fixed_t *forwardmove;
extern int mouse_sensitivity;
extern int mouse_sensitivity_y;
extern int mouse_sensitivity_strafe;
extern int mouse_sensitivity_y_look;
extern boolean mouse_y_invert;
extern int mouse_acceleration;
extern int mouse_acceleration_threshold;
extern int mousex;
extern int mousey;
extern fixed_t forwardmove[2];
extern fixed_t default_sidemove[2];
extern fixed_t *sidemove;
extern const fixed_t angleturn[3];
extern int default_skill; //jff 3/24/98 default skill
extern boolean haswolflevels; //jff 4/18/98 wolf levels present

456
src/g_input.c Normal file
View File

@ -0,0 +1,456 @@
//
// Copyright(C) 2024 ceski
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Game Input Utility Functions
//
#include <math.h>
#include <string.h>
#include "d_main.h"
#include "g_game.h"
#include "i_gamepad.h"
#include "i_timer.h"
#include "i_video.h"
#include "p_mobj.h"
#include "r_state.h"
//
// Local View
//
void (*G_UpdateLocalView)(void);
void G_ClearLocalView(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;
}
//
// Side Movement
//
static int (*RoundSide)(double side);
static int RoundSide_Strict(double side)
{
return lround(side * 0.5) * 2; // Even values only.
}
static int RoundSide_Full(double side)
{
return lround(side);
}
void G_UpdateSideMove(void)
{
if (strictmode || (netgame && !solonet))
{
RoundSide = RoundSide_Strict;
sidemove = default_sidemove;
}
else
{
RoundSide = RoundSide_Full;
sidemove = autostrafe50 ? forwardmove : default_sidemove;
}
}
//
// Error Accumulation
//
// Round to nearest 256 for single byte turning. From Chocolate Doom.
#define BYTE_TURN(x) (((x) + 128) & 0xFF00)
typedef struct
{
double angle;
double pitch;
double side;
double vert;
} carry_t;
static carry_t prevcarry, carry;
static short (*CarryAngleTic)(double angle);
static short (*CarryAngle)(double angle);
void G_UpdateCarry(void)
{
prevcarry = carry;
}
void G_ClearCarry(void)
{
memset(&prevcarry, 0, sizeof(prevcarry));
memset(&carry, 0, sizeof(carry));
}
static int CarryError(double value, const double *prevcarry, double *carry)
{
const double desired = value + *prevcarry;
const int actual = lround(desired);
*carry = desired - actual;
return actual;
}
static short CarryAngleTic_Full(double angle)
{
return CarryError(angle, &prevcarry.angle, &carry.angle);
}
static short CarryAngle_Full(double angle)
{
const short fullres = CarryAngleTic_Full(angle);
localview.angle = fullres << FRACBITS;
return fullres;
}
static short CarryAngle_FakeLongTics(double angle)
{
return (localview.angleoffset = BYTE_TURN(CarryAngle_Full(angle)));
}
static short CarryAngleTic_LowRes(double angle)
{
const double fullres = angle + prevcarry.angle;
const short lowres = BYTE_TURN((short)lround(fullres));
carry.angle = fullres - lowres;
return lowres;
}
static short CarryAngle_LowRes(double angle)
{
const short lowres = CarryAngleTic_LowRes(angle);
localview.angle = lowres << FRACBITS;
return lowres;
}
void G_UpdateAngleFunctions(void)
{
CarryAngleTic = lowres_turn ? CarryAngleTic_LowRes : CarryAngleTic_Full;
CarryAngle = CarryAngleTic;
G_UpdateLocalView = G_ClearLocalView;
if (raw_input && (!netgame || solonet))
{
if (lowres_turn && fake_longtics)
{
CarryAngle = CarryAngle_FakeLongTics;
G_UpdateLocalView = UpdateLocalView_FakeLongTics;
}
else if (uncapped)
{
CarryAngle = lowres_turn ? CarryAngle_LowRes : CarryAngle_Full;
}
}
}
static int CarryPitch(double pitch)
{
return (localview.pitch =
CarryError(pitch, &prevcarry.pitch, &carry.pitch));
}
static int CarrySide(double side)
{
const double desired = side + prevcarry.side;
const int actual = RoundSide(desired);
carry.side = desired - actual;
return actual;
}
static int CarryVert(double vert)
{
return CarryError(vert, &prevcarry.vert, &carry.vert);
}
//
// Gamepad
//
static const int direction[] = {1, -1};
static double deltatics;
void G_UpdateDeltaTics(void)
{
if (uncapped && raw_input)
{
static uint64_t last_time;
const uint64_t current_time = I_GetTimeUS();
if (input_ready)
{
const uint64_t delta_time = current_time - last_time;
deltatics = (double)delta_time * TICRATE / 1000000.0;
deltatics = BETWEEN(0.0, 1.0, deltatics);
}
else
{
deltatics = 0.0;
}
last_time = current_time;
}
else
{
deltatics = 1.0;
}
}
short G_CalcControllerAngle(void)
{
localview.rawangle -= (deltatics * axes[AXIS_TURN] * angleturn[1]
* direction[joy_invert_turn]);
return CarryAngle(localview.rawangle);
}
int G_CalcControllerPitch(void)
{
localview.rawpitch -= (deltatics * axes[AXIS_LOOK] * angleturn[1]
* direction[joy_invert_look] * FRACUNIT);
return CarryPitch(localview.rawpitch);
}
int G_CalcControllerSideTurn(int speed)
{
const int side = RoundSide(axes[AXIS_TURN] * forwardmove[speed]
* direction[joy_invert_turn]);
return BETWEEN(-forwardmove[speed], forwardmove[speed], side);
}
int G_CalcControllerSideStrafe(int speed)
{
const int side = RoundSide(axes[AXIS_STRAFE] * forwardmove[speed]
* direction[joy_invert_strafe]);
return BETWEEN(-sidemove[speed], sidemove[speed], side);
}
int G_CalcControllerForward(int speed)
{
const int forward = lroundf(axes[AXIS_FORWARD] * forwardmove[speed]
* direction[joy_invert_forward]);
return BETWEEN(-forwardmove[speed], forwardmove[speed], forward);
}
//
// Mouse
//
static double (*AccelerateMouse)(int val);
static double AccelerateMouse_Threshold(int val)
{
if (val < 0)
{
return -AccelerateMouse_Threshold(-val);
}
if (val > mouse_acceleration_threshold)
{
return ((double)(val - mouse_acceleration_threshold)
* (mouse_acceleration + 10) / 10
+ mouse_acceleration_threshold);
}
else
{
return val;
}
}
static double AccelerateMouse_NoThreshold(int val)
{
return ((double)val * (mouse_acceleration + 10) / 10);
}
static double AccelerateMouse_Skip(int val)
{
return val;
}
void G_UpdateAccelerateMouse(void)
{
if (mouse_acceleration)
{
AccelerateMouse = raw_input ? AccelerateMouse_NoThreshold
: AccelerateMouse_Threshold;
}
else
{
AccelerateMouse = AccelerateMouse_Skip;
}
}
short G_CalcMouseAngle(void)
{
if (mouse_sensitivity)
{
localview.rawangle -= (AccelerateMouse(mousex)
* (mouse_sensitivity + 5) * 8 / 10);
return CarryAngle(localview.rawangle);
}
else
{
return 0;
}
}
int G_CalcMousePitch(void)
{
if (mouse_sensitivity_y_look)
{
localview.rawpitch += (AccelerateMouse(mousey)
* (mouse_sensitivity_y_look + 5) * 8 / 10
* direction[mouse_y_invert] * FRACUNIT);
return CarryPitch(localview.rawpitch);
}
else
{
return 0;
}
}
int G_CalcMouseSide(void)
{
if (mouse_sensitivity_strafe)
{
const double side = (AccelerateMouse(mousex)
* (mouse_sensitivity_strafe + 5) * 2 / 10);
return CarrySide(side);
}
else
{
return 0;
}
}
int G_CalcMouseVert(void)
{
if (mouse_sensitivity_y)
{
const double vert = (AccelerateMouse(mousey)
* (mouse_sensitivity_y + 5) / 10);
return CarryVert(vert);
}
else
{
return 0;
}
}
//
// Composite Turn
//
static angle_t saved_angle;
void G_SavePlayerAngle(const player_t *player)
{
saved_angle = player->mo->angle;
}
void G_AddToTicAngle(player_t *player)
{
player->ticangle += player->mo->angle - saved_angle;
}
void G_UpdateTicAngleTurn(ticcmd_t *cmd, int angle)
{
const short old_angleturn = cmd->angleturn;
cmd->angleturn = CarryAngleTic(localview.rawangle + angle);
cmd->ticangleturn = cmd->angleturn - old_angleturn;
}
//
// Quickstart Cache
// When recording a demo and the map is reloaded, cached input from a circular
// buffer can be applied prior to the screen wipe. Adapted from DSDA-Doom.
//
int quickstart_cache_tics;
boolean quickstart_queued;
float axis_turn_tic;
int mousex_tic;
void G_ClearQuickstartTic(void)
{
axis_turn_tic = 0.0f;
mousex_tic = 0;
}
void G_ApplyQuickstartCache(ticcmd_t *cmd, boolean strafe)
{
static float axis_turn_cache[TICRATE];
static int mousex_cache[TICRATE];
static short angleturn_cache[TICRATE];
static int index;
if (quickstart_cache_tics < 1)
{
return;
}
if (quickstart_queued)
{
axes[AXIS_TURN] = 0.0f;
mousex = 0;
if (strafe)
{
for (int i = 0; i < quickstart_cache_tics; i++)
{
axes[AXIS_TURN] += axis_turn_cache[i];
mousex += mousex_cache[i];
}
cmd->angleturn = 0;
localview.rawangle = 0.0;
}
else
{
short result = 0;
for (int i = 0; i < quickstart_cache_tics; i++)
{
result += angleturn_cache[i];
}
cmd->angleturn = CarryAngleTic(result);
localview.rawangle = cmd->angleturn;
}
memset(axis_turn_cache, 0, sizeof(axis_turn_cache));
memset(mousex_cache, 0, sizeof(mousex_cache));
memset(angleturn_cache, 0, sizeof(angleturn_cache));
index = 0;
quickstart_queued = false;
}
else
{
axis_turn_cache[index] = axis_turn_tic;
mousex_cache[index] = mousex_tic;
angleturn_cache[index] = cmd->angleturn;
index = (index + 1) % quickstart_cache_tics;
}
}

73
src/g_input.h Normal file
View File

@ -0,0 +1,73 @@
//
// Copyright(C) 2024 ceski
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// DESCRIPTION:
// Game Input Utility Functions
//
#ifndef __G_INPUT__
#define __G_INPUT__
#include "doomtype.h"
struct player_s;
struct ticcmd_s;
// Local View
extern void (*G_UpdateLocalView)(void);
void G_ClearLocalView(void);
// Side Movement
void G_UpdateSideMove(void);
// Error Accumulation
void G_UpdateCarry(void);
void G_ClearCarry(void);
void G_UpdateAngleFunctions(void);
// Gamepad
void G_UpdateDeltaTics(void);
short G_CalcControllerAngle(void);
int G_CalcControllerPitch(void);
int G_CalcControllerSideTurn(int speed);
int G_CalcControllerSideStrafe(int speed);
int G_CalcControllerForward(int speed);
// Mouse
void G_UpdateAccelerateMouse(void);
short G_CalcMouseAngle(void);
int G_CalcMousePitch(void);
int G_CalcMouseSide(void);
int G_CalcMouseVert(void);
// Composite Turn
void G_SavePlayerAngle(const struct player_s *player);
void G_AddToTicAngle(struct player_s *player);
void G_UpdateTicAngleTurn(struct ticcmd_s *cmd, int angle);
// Quickstart Cache
extern int quickstart_cache_tics;
extern boolean quickstart_queued;
extern float axis_turn_tic;
extern int mousex_tic;
void G_ClearQuickstartTic(void);
void G_ApplyQuickstartCache(struct ticcmd_s *cmd, boolean strafe);
#endif

View File

@ -24,7 +24,6 @@
#include "i_printf.h"
#include "i_system.h"
#include "m_config.h"
#include "r_main.h"
#define AXIS_BUTTON_DEADZONE (SDL_JOYSTICK_AXIS_MAX / 3)
@ -463,59 +462,6 @@ void I_DelayEvent(void)
//
// Read the change in mouse state to generate mouse motion events
//
// This is to combine all mouse movement for a tic into one mouse
// motion event.
// The mouse input values are input directly to the game, but when the values
// exceed the value of mouse_acceleration_threshold, they are multiplied by
// mouse_acceleration to increase the speed.
static int mouse_acceleration;
static int mouse_acceleration_threshold;
static double AccelerateMouse_Thresh(int val)
{
if (val < 0)
{
return -AccelerateMouse_Thresh(-val);
}
if (val > mouse_acceleration_threshold)
{
return ((double)(val - mouse_acceleration_threshold)
* (mouse_acceleration + 10) / 10
+ mouse_acceleration_threshold);
}
else
{
return val;
}
}
static double AccelerateMouse_NoThresh(int val)
{
return ((double)val * (mouse_acceleration + 10) / 10);
}
static double AccelerateMouse_Skip(int val)
{
return val;
}
double (*I_AccelerateMouse)(int val) = AccelerateMouse_NoThresh;
void I_UpdateAccelerateMouse(void)
{
if (mouse_acceleration)
{
I_AccelerateMouse =
raw_input ? AccelerateMouse_NoThresh : AccelerateMouse_Thresh;
}
else
{
I_AccelerateMouse = AccelerateMouse_Skip;
}
}
void I_ReadMouse(void)
{
@ -593,11 +539,3 @@ void I_HandleKeyboardEvent(SDL_Event *sdlevent)
break;
}
}
void I_BindInputVariables(void)
{
BIND_NUM_GENERAL(mouse_acceleration, 10, 0, 40,
"Mouse acceleration (0 = 1.0; 40 = 5.0)");
BIND_NUM(mouse_acceleration_threshold, 10, 0, 32,
"Mouse acceleration threshold");
}

View File

@ -26,8 +26,6 @@ void I_InitController(void);
void I_OpenController(int which);
void I_CloseController(int which);
extern double (*I_AccelerateMouse)(int val);
void I_UpdateAccelerateMouse(void);
void I_ReadMouse(void);
void I_UpdateJoystick(boolean axis_buttons);
void I_UpdateJoystickMenu(void);
@ -37,6 +35,4 @@ void I_HandleJoystickEvent(SDL_Event *sdlevent);
void I_HandleKeyboardEvent(SDL_Event *sdlevent);
void I_HandleMouseEvent(SDL_Event *sdlevent);
void I_BindInputVariables(void);
#endif

View File

@ -37,7 +37,6 @@
#include "hu_stuff.h"
#include "i_gamepad.h"
#include "i_printf.h"
#include "i_input.h"
#include "i_sound.h"
#include "i_system.h"
#include "i_video.h"
@ -117,7 +116,6 @@ void M_InitConfig(void)
G_BindGameVariables();
G_BindGameInputVariables();
I_BindInputVariables();
I_BindGamepadVariables();
M_BindInputVariables();

View File

@ -25,7 +25,6 @@
#include "hu_lib.h"
#include "hu_stuff.h"
#include "i_gamepad.h"
#include "i_input.h"
#include "i_oalsound.h"
#include "i_sound.h"
#include "i_timer.h"
@ -2158,7 +2157,7 @@ static setup_menu_t gen_settings3[] = {
MI_GAP,
{"Mouse acceleration", S_THERMO, CNTR_X, M_THRM_SPC, {"mouse_acceleration"},
m_null, input_null, str_mouse_accel, I_UpdateAccelerateMouse},
m_null, input_null, str_mouse_accel, G_UpdateAccelerateMouse},
MI_END
};

View File

@ -22,6 +22,7 @@
#include "d_items.h"
#include "d_player.h"
#include "doomstat.h"
#include "g_input.h"
#include "i_printf.h"
#include "i_video.h" // uncapped
#include "m_random.h"
@ -649,18 +650,6 @@ 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
//
@ -697,10 +686,10 @@ void A_Punch(player_t *player, pspdef_t *psp)
// turn to face target
SavePlayerAngle(player);
G_SavePlayerAngle(player);
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y,
linetarget->x, linetarget->y);
AddToTicAngle(player);
G_AddToTicAngle(player);
}
//
@ -743,7 +732,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);
G_SavePlayerAngle(player);
if (angle - player->mo->angle > ANG180)
if ((signed int) (angle - player->mo->angle) < -ANG90/20)
player->mo->angle = angle + ANG90/21;
@ -754,7 +743,7 @@ void A_Saw(player_t *player, pspdef_t *psp)
player->mo->angle = angle - ANG90/21;
else
player->mo->angle += ANG90/20;
AddToTicAngle(player);
G_AddToTicAngle(player);
player->mo->flags |= MF_JUSTATTACKED;
}
@ -1318,9 +1307,9 @@ void A_WeaponMeleeAttack(player_t *player, pspdef_t *psp)
S_StartSound(player->mo, hitsound);
// turn to face target
SavePlayerAngle(player);
G_SavePlayerAngle(player);
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, linetarget->x, linetarget->y);
AddToTicAngle(player);
G_AddToTicAngle(player);
}
//

View File

@ -70,7 +70,6 @@ fixed_t skyiscale;
fixed_t viewx, viewy, viewz;
angle_t viewangle;
localview_t localview;
double deltatics;
boolean raw_input;
fixed_t viewcos, viewsin;
player_t *viewplayer;

View File

@ -153,9 +153,6 @@ inline static angle_t LerpAngle(angle_t oangle, angle_t nangle)
}
}
extern double deltatics;
extern boolean raw_input;
extern int autodetect_hom;
#endif

View File

@ -106,6 +106,7 @@ extern fixed_t viewy;
extern fixed_t viewz;
extern angle_t viewangle;
extern localview_t localview; // View orientation offsets for current frame.
extern boolean raw_input;
extern struct player_s *viewplayer;
extern angle_t clipangle;
extern angle_t vx_clipangle;