mirror of
https://github.com/fabiangreffrath/woof.git
synced 2025-09-26 22:44:30 -04:00
More mouse improvements (#1348)
* Check `oldlookdir` before disabling `centering` When turning off mouselook/padlook, keep view centering enabled until `oldlookdir` is zero, meaning when the player's view actually appears centered. * Move `viewangleoffset` * Check dead state set by `P_KillMobj()` * Smooth composite/mouse turning transitions Blend interpolated composite input (e.g. keyboard) turning with direct mouse turning to prevent choppy transitions. * Group inputs by composite/gamepad/mouse * Update carry/input calculations This also enables shorttics (lowres_turn) with fast mouse polling. * Add mouse smoothing toggle With mouse smoothing disabled (default), mouse movements are immediately reflected in each frame update, with the game simulation following behind. The higher the framerate, the lower the perceived input lag. With mouse smoothing enabled, mouse movements are delayed by up to one tic (~29 ms) due to interpolation. When recording older format demos with reduced turning resolution (or when using `-shorttics`), interpolation may still be preferred for smoother turning. * Rename "mouse smoothing" to "raw mouse input" * Skip calculations when using interpolation
This commit is contained in:
parent
e0d30bbe6e
commit
1a9d580bd5
@ -174,9 +174,10 @@ int eventhead, eventtail;
|
|||||||
//
|
//
|
||||||
void D_PostEvent(event_t *ev)
|
void D_PostEvent(event_t *ev)
|
||||||
{
|
{
|
||||||
if (ev->type == ev_mouse && !menuactive && gamestate == GS_LEVEL && !paused)
|
if (ev->type == ev_mouse)
|
||||||
{
|
{
|
||||||
G_MouseMovementResponder(ev);
|
G_MouseMovementResponder(ev);
|
||||||
|
G_PrepTiccmd();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +240,9 @@ void D_Display (void)
|
|||||||
// [AM] Figure out how far into the current tic we're in as a fixed_t.
|
// [AM] Figure out how far into the current tic we're in as a fixed_t.
|
||||||
fractionaltic = I_GetFracTime();
|
fractionaltic = I_GetFracTime();
|
||||||
|
|
||||||
if (window_focused)
|
if (!menuactive && gamestate == GS_LEVEL && !paused && mouse_raw_input)
|
||||||
{
|
{
|
||||||
I_ReadMouse();
|
I_StartDisplay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
410
src/g_game.c
410
src/g_game.c
@ -171,19 +171,18 @@ static int mousex;
|
|||||||
static int mousey;
|
static int mousey;
|
||||||
boolean dclick;
|
boolean dclick;
|
||||||
|
|
||||||
// Skip mouse if using a controller and recording in strict mode (DSDA rule).
|
typedef struct carry_s
|
||||||
static boolean skip_mouse = true;
|
|
||||||
|
|
||||||
typedef struct cmd_carry_s
|
|
||||||
{
|
{
|
||||||
double angle;
|
double angle;
|
||||||
double pitch;
|
double pitch;
|
||||||
double strafe;
|
double side;
|
||||||
double vert;
|
double vert;
|
||||||
} cmd_carry_t;
|
short lowres;
|
||||||
|
} carry_t;
|
||||||
|
|
||||||
static cmd_carry_t cmd_prev_carry;
|
static carry_t prevcarry;
|
||||||
static cmd_carry_t cmd_carry;
|
static carry_t carry;
|
||||||
|
static ticcmd_t basecmd;
|
||||||
|
|
||||||
boolean joyarray[MAX_JSB+1]; // [FG] support more joystick buttons
|
boolean joyarray[MAX_JSB+1]; // [FG] support more joystick buttons
|
||||||
boolean *joybuttons = &joyarray[1]; // allow [-1]
|
boolean *joybuttons = &joyarray[1]; // allow [-1]
|
||||||
@ -369,93 +368,101 @@ static void G_DemoSkipTics(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CarryError(double value, double *prev_carry, double *carry)
|
static int CarryError(double value, const double *prevcarry, double *carry)
|
||||||
{
|
{
|
||||||
const double desired = value + *prev_carry;
|
const double desired = value + *prevcarry;
|
||||||
const int actual = lround(desired);
|
const int actual = lround(desired);
|
||||||
*carry = desired - actual;
|
*carry = desired - actual;
|
||||||
return actual;
|
return actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CalcMouseAngle(int mousex)
|
static int CarryAngle(double angle)
|
||||||
{
|
{
|
||||||
if (mouseSensitivity_horiz)
|
return CarryError(angle, &prevcarry.angle, &carry.angle);
|
||||||
{
|
|
||||||
const double angle = (I_AccelerateMouse(mousex) *
|
|
||||||
(mouseSensitivity_horiz + 5) * 8 / 10);
|
|
||||||
return CarryError(angle, &cmd_prev_carry.angle, &cmd_carry.angle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd_prev_carry.angle = 0.0;
|
|
||||||
cmd_carry.angle = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CalcMousePitch(int mousey)
|
static int CarryMousePitch(double pitch)
|
||||||
{
|
{
|
||||||
if (mouseSensitivity_vert_look)
|
return CarryError(pitch, &prevcarry.pitch, &carry.pitch);
|
||||||
{
|
|
||||||
const double pitch = (I_AccelerateMouse(mouse_y_invert ? -mousey : mousey) *
|
|
||||||
(mouseSensitivity_vert_look + 5) / 10);
|
|
||||||
return CarryError(pitch, &cmd_prev_carry.pitch, &cmd_carry.pitch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd_prev_carry.pitch = 0.0;
|
|
||||||
cmd_carry.pitch = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CalcMouseStrafe(int mousex)
|
static int CarryMouseVert(double vert)
|
||||||
{
|
{
|
||||||
if (mouseSensitivity_horiz_strafe)
|
return CarryError(vert, &prevcarry.vert, &carry.vert);
|
||||||
{
|
|
||||||
const double desired = (cmd_prev_carry.strafe + I_AccelerateMouse(mousex) *
|
|
||||||
(mouseSensitivity_horiz_strafe + 5) * 2 / 10);
|
|
||||||
const int actual = lround(desired * 0.5) * 2; // Even values only.
|
|
||||||
cmd_carry.strafe = desired - actual;
|
|
||||||
return actual;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd_prev_carry.strafe = 0.0;
|
|
||||||
cmd_carry.strafe = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CalcMouseVert(int mousey)
|
static int CarryMouseSide(double side)
|
||||||
{
|
{
|
||||||
if (mouseSensitivity_vert)
|
const double desired = side + prevcarry.side;
|
||||||
{
|
const int actual = lround(desired * 0.5) * 2; // Even values only.
|
||||||
const double vert = (I_AccelerateMouse(mousey) *
|
carry.side = desired - actual;
|
||||||
(mouseSensitivity_vert + 5) / 10);
|
return actual;
|
||||||
return CarryError(vert, &cmd_prev_carry.vert, &cmd_carry.vert);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd_prev_carry.vert = 0.0;
|
|
||||||
cmd_carry.vert = 0.0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void G_MouseMovementResponder(const event_t *ev)
|
static short CarryLowResAngle(short angle)
|
||||||
{
|
{
|
||||||
if (strictmode && demorecording && skip_mouse)
|
const short desired = angle + prevcarry.lowres;
|
||||||
return;
|
// Round to nearest 256 for single byte turning. From Chocolate Doom.
|
||||||
|
const short actual = (desired + 128) & 0xFF00;
|
||||||
|
carry.lowres = desired - actual;
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
mousex += ev->data2;
|
static double CalcMouseAngle(int mousex)
|
||||||
mousey += ev->data3;
|
{
|
||||||
|
if (!mouseSensitivity_horiz)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return (I_AccelerateMouse(mousex) * (mouseSensitivity_horiz + 5) * 8 / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double CalcMousePitch(int mousey)
|
||||||
|
{
|
||||||
|
if (!mouseSensitivity_vert_look)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return (I_AccelerateMouse(mousey) * direction[mouse_y_invert] *
|
||||||
|
(mouseSensitivity_vert_look + 5) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double CalcMouseSide(int mousex)
|
||||||
|
{
|
||||||
|
if (!mouseSensitivity_horiz_strafe)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return (I_AccelerateMouse(mousex) *
|
||||||
|
(mouseSensitivity_horiz_strafe + 5) * 2 / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double CalcMouseVert(int mousey)
|
||||||
|
{
|
||||||
|
if (!mouseSensitivity_vert)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return (I_AccelerateMouse(mousey) * (mouseSensitivity_vert + 5) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void G_PrepTiccmd(void)
|
||||||
|
{
|
||||||
|
ticcmd_t *cmd = &basecmd;
|
||||||
|
|
||||||
if (!M_InputGameActive(input_strafe))
|
if (!M_InputGameActive(input_strafe))
|
||||||
localview.angle = CalcMouseAngle(mousex);
|
{
|
||||||
|
localview.rawangle = -CalcMouseAngle(mousex);
|
||||||
|
cmd->angleturn = CarryAngle(localview.rawangle);
|
||||||
|
if (lowres_turn)
|
||||||
|
{
|
||||||
|
cmd->angleturn = CarryLowResAngle(cmd->angleturn);
|
||||||
|
}
|
||||||
|
localview.angle = cmd->angleturn << 16;
|
||||||
|
}
|
||||||
|
|
||||||
if (mouselook)
|
if (mouselook)
|
||||||
localview.pitch = CalcMousePitch(mousey);
|
{
|
||||||
|
const double pitch = CalcMousePitch(mousey);
|
||||||
|
cmd->lookdir = CarryMousePitch(pitch);
|
||||||
|
localview.pitch = cmd->lookdir;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -467,98 +474,67 @@ void G_MouseMovementResponder(const event_t *ev)
|
|||||||
|
|
||||||
void G_BuildTiccmd(ticcmd_t* cmd)
|
void G_BuildTiccmd(ticcmd_t* cmd)
|
||||||
{
|
{
|
||||||
boolean strafe;
|
const boolean strafe = M_InputGameActive(input_strafe);
|
||||||
int speed;
|
const boolean turnleft = M_InputGameActive(input_turnleft);
|
||||||
int tspeed;
|
const boolean turnright = M_InputGameActive(input_turnright);
|
||||||
int forward;
|
// [FG] speed key inverts autorun
|
||||||
int side;
|
const int speed = autorun ^ M_InputGameActive(input_speed); // phares
|
||||||
|
int angle = 0;
|
||||||
|
int pitch = 0;
|
||||||
|
int forward = 0;
|
||||||
|
int side = 0;
|
||||||
int newweapon; // phares
|
int newweapon; // phares
|
||||||
ticcmd_t *base;
|
|
||||||
|
|
||||||
extern boolean boom_weapon_state_injection;
|
extern boolean boom_weapon_state_injection;
|
||||||
static boolean done_autoswitch = false;
|
static boolean done_autoswitch = false;
|
||||||
|
|
||||||
// Assume localview can be used unless mouse input is interrupted by other
|
// Assume localview can be used unless mouse input is interrupted by other
|
||||||
// inputs that apply turning or looking up/down (e.g. keyboard or gamepad).
|
// inputs that apply looking up/down (e.g. gamepad).
|
||||||
localview.useangle = !lowres_turn;
|
|
||||||
localview.usepitch = true;
|
localview.usepitch = true;
|
||||||
|
|
||||||
G_DemoSkipTics();
|
G_DemoSkipTics();
|
||||||
|
|
||||||
base = I_BaseTiccmd(); // empty, or external driver
|
memcpy(cmd, &basecmd, sizeof(*cmd));
|
||||||
memcpy(cmd, base, sizeof *cmd);
|
memset(&basecmd, 0, sizeof(basecmd));
|
||||||
|
|
||||||
cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
|
cmd->consistancy = consistancy[consoleplayer][maketic%BACKUPTICS];
|
||||||
|
|
||||||
strafe = M_InputGameActive(input_strafe);
|
// Composite input
|
||||||
// [FG] speed key inverts autorun
|
|
||||||
speed = autorun ^ M_InputGameActive(input_speed); // phares
|
|
||||||
|
|
||||||
forward = side = 0;
|
|
||||||
|
|
||||||
// use two stage accelerative turning
|
|
||||||
// on the keyboard and joystick
|
|
||||||
if (M_InputGameActive(input_turnleft) ||
|
|
||||||
M_InputGameActive(input_turnright))
|
|
||||||
turnheld += ticdup;
|
|
||||||
else
|
|
||||||
turnheld = 0;
|
|
||||||
|
|
||||||
if (turnheld < SLOWTURNTICS)
|
|
||||||
tspeed = 2; // slow turn
|
|
||||||
else
|
|
||||||
tspeed = speed;
|
|
||||||
|
|
||||||
// turn 180 degrees in one keystroke? // phares
|
// turn 180 degrees in one keystroke? // phares
|
||||||
// |
|
if (STRICTMODE(M_InputGameActive(input_reverse)))
|
||||||
if (STRICTMODE(M_InputGameActive(input_reverse))) // V
|
{
|
||||||
{
|
angle += QUICKREVERSE;
|
||||||
cmd->angleturn += (short)QUICKREVERSE; // ^
|
M_InputGameDeactivate(input_reverse);
|
||||||
localview.useangle = false;
|
}
|
||||||
M_InputGameDeactivate(input_reverse); // |
|
|
||||||
} // phares
|
|
||||||
|
|
||||||
// let movement keys cancel each other out
|
// let movement keys cancel each other out
|
||||||
|
if (turnleft || turnright)
|
||||||
|
{
|
||||||
|
turnheld += ticdup;
|
||||||
|
|
||||||
if (strafe)
|
if (strafe)
|
||||||
{
|
{
|
||||||
if (M_InputGameActive(input_turnright))
|
if (turnright)
|
||||||
side += sidemove[speed];
|
side += sidemove[speed];
|
||||||
if (M_InputGameActive(input_turnleft))
|
if (turnleft)
|
||||||
side -= sidemove[speed];
|
side -= sidemove[speed];
|
||||||
|
|
||||||
if (analog_controls && controller_axes[axis_turn])
|
|
||||||
{
|
|
||||||
fixed_t x = axis_move_sens * controller_axes[axis_turn] / 10;
|
|
||||||
x = direction[invert_turn] * x;
|
|
||||||
side += FixedMul(sidemove[speed], x);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (M_InputGameActive(input_turnright))
|
// use two stage accelerative turning on the keyboard and joystick
|
||||||
{
|
const int tspeed = ((turnheld < SLOWTURNTICS) ? 2 : speed);
|
||||||
cmd->angleturn -= angleturn[tspeed];
|
|
||||||
localview.useangle = false;
|
|
||||||
}
|
|
||||||
if (M_InputGameActive(input_turnleft))
|
|
||||||
{
|
|
||||||
cmd->angleturn += angleturn[tspeed];
|
|
||||||
localview.useangle = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (analog_controls && controller_axes[axis_turn])
|
if (turnright)
|
||||||
{
|
angle -= angleturn[tspeed];
|
||||||
fixed_t x = controller_axes[axis_turn];
|
if (turnleft)
|
||||||
|
angle += angleturn[tspeed];
|
||||||
// response curve to compensate for lack of near-centered accuracy
|
|
||||||
x = FixedMul(FixedMul(x, x), x);
|
|
||||||
|
|
||||||
x = direction[invert_turn] * axis_turn_sens * x / 10;
|
|
||||||
cmd->angleturn -= FixedMul(angleturn[1], x);
|
|
||||||
localview.useangle = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turnheld = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (M_InputGameActive(input_forward))
|
if (M_InputGameActive(input_forward))
|
||||||
forward += forwardmove[speed];
|
forward += forwardmove[speed];
|
||||||
@ -569,14 +545,37 @@ void G_BuildTiccmd(ticcmd_t* cmd)
|
|||||||
if (M_InputGameActive(input_strafeleft))
|
if (M_InputGameActive(input_strafeleft))
|
||||||
side -= sidemove[speed];
|
side -= sidemove[speed];
|
||||||
|
|
||||||
|
// Gamepad
|
||||||
|
|
||||||
if (analog_controls)
|
if (analog_controls)
|
||||||
{
|
{
|
||||||
|
if (controller_axes[axis_turn])
|
||||||
|
{
|
||||||
|
if (strafe)
|
||||||
|
{
|
||||||
|
fixed_t x = axis_move_sens * controller_axes[axis_turn] / 10;
|
||||||
|
x = direction[invert_turn] * x;
|
||||||
|
side += FixedMul(sidemove[speed], x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed_t x = controller_axes[axis_turn];
|
||||||
|
|
||||||
|
// response curve to compensate for lack of near-centered accuracy
|
||||||
|
x = FixedMul(FixedMul(x, x), x);
|
||||||
|
|
||||||
|
x = direction[invert_turn] * axis_turn_sens * x / 10;
|
||||||
|
angle -= FixedMul(angleturn[1], x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (controller_axes[axis_forward])
|
if (controller_axes[axis_forward])
|
||||||
{
|
{
|
||||||
fixed_t y = axis_move_sens * controller_axes[axis_forward] / 10;
|
fixed_t y = axis_move_sens * controller_axes[axis_forward] / 10;
|
||||||
y = direction[invert_forward] * y;
|
y = direction[invert_forward] * y;
|
||||||
forward -= FixedMul(forwardmove[speed], y);
|
forward -= FixedMul(forwardmove[speed], y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller_axes[axis_strafe])
|
if (controller_axes[axis_strafe])
|
||||||
{
|
{
|
||||||
fixed_t x = axis_move_sens * controller_axes[axis_strafe] / 10;
|
fixed_t x = axis_move_sens * controller_axes[axis_strafe] / 10;
|
||||||
@ -592,12 +591,63 @@ void G_BuildTiccmd(ticcmd_t* cmd)
|
|||||||
y = FixedMul(FixedMul(y, y), y);
|
y = FixedMul(FixedMul(y, y), y);
|
||||||
|
|
||||||
y = direction[invert_look] * axis_look_sens * y / 10;
|
y = direction[invert_look] * axis_look_sens * y / 10;
|
||||||
cmd->lookdir -= FixedMul(lookspeed[0], y);
|
pitch -= FixedMul(lookspeed[0], y);
|
||||||
localview.usepitch = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// buttons
|
// Mouse
|
||||||
|
|
||||||
|
if (strafe)
|
||||||
|
{
|
||||||
|
const double mouseside = CalcMouseSide(mousex);
|
||||||
|
side += CarryMouseSide(mouseside);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mouselook && !novert)
|
||||||
|
{
|
||||||
|
const double mousevert = CalcMouseVert(mousey);
|
||||||
|
forward += CarryMouseVert(mousevert);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update/reset
|
||||||
|
|
||||||
|
if (angle)
|
||||||
|
{
|
||||||
|
angle = CarryAngle(localview.rawangle + angle);
|
||||||
|
if (lowres_turn)
|
||||||
|
{
|
||||||
|
angle = CarryLowResAngle(angle);
|
||||||
|
}
|
||||||
|
localview.ticangleturn = angle - cmd->angleturn;
|
||||||
|
cmd->angleturn = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pitch)
|
||||||
|
{
|
||||||
|
cmd->lookdir = pitch;
|
||||||
|
localview.usepitch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forward > MAXPLMOVE)
|
||||||
|
forward = MAXPLMOVE;
|
||||||
|
else if (forward < -MAXPLMOVE)
|
||||||
|
forward = -MAXPLMOVE;
|
||||||
|
if (side > MAXPLMOVE)
|
||||||
|
side = MAXPLMOVE;
|
||||||
|
else if (side < -MAXPLMOVE)
|
||||||
|
side = -MAXPLMOVE;
|
||||||
|
|
||||||
|
cmd->forwardmove = forward;
|
||||||
|
cmd->sidemove = side;
|
||||||
|
|
||||||
|
mousex = mousey = 0;
|
||||||
|
localview.angle = 0;
|
||||||
|
localview.pitch = 0;
|
||||||
|
localview.rawangle = 0.0;
|
||||||
|
prevcarry = carry;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
|
||||||
cmd->chatchar = HU_dequeueChatChar();
|
cmd->chatchar = HU_dequeueChatChar();
|
||||||
|
|
||||||
if (M_InputGameActive(input_fire))
|
if (M_InputGameActive(input_fire))
|
||||||
@ -716,33 +766,6 @@ void G_BuildTiccmd(ticcmd_t* cmd)
|
|||||||
cmd->buttons |= BT_USE;
|
cmd->buttons |= BT_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strafe)
|
|
||||||
side += CalcMouseStrafe(mousex);
|
|
||||||
else
|
|
||||||
cmd->angleturn -= localview.angle;
|
|
||||||
|
|
||||||
if (mouselook)
|
|
||||||
cmd->lookdir += localview.pitch;
|
|
||||||
else if (!novert)
|
|
||||||
forward += CalcMouseVert(mousey);
|
|
||||||
|
|
||||||
mousex = mousey = 0;
|
|
||||||
localview.angle = 0;
|
|
||||||
localview.pitch = 0;
|
|
||||||
cmd_prev_carry = cmd_carry;
|
|
||||||
|
|
||||||
if (forward > MAXPLMOVE)
|
|
||||||
forward = MAXPLMOVE;
|
|
||||||
else if (forward < -MAXPLMOVE)
|
|
||||||
forward = -MAXPLMOVE;
|
|
||||||
if (side > MAXPLMOVE)
|
|
||||||
side = MAXPLMOVE;
|
|
||||||
else if (side < -MAXPLMOVE)
|
|
||||||
side = -MAXPLMOVE;
|
|
||||||
|
|
||||||
cmd->forwardmove += forward;
|
|
||||||
cmd->sidemove += side;
|
|
||||||
|
|
||||||
// special buttons
|
// special buttons
|
||||||
if (sendpause)
|
if (sendpause)
|
||||||
{
|
{
|
||||||
@ -768,26 +791,6 @@ void G_BuildTiccmd(ticcmd_t* cmd)
|
|||||||
sendjoin = false;
|
sendjoin = false;
|
||||||
cmd->buttons |= BT_JOIN;
|
cmd->buttons |= BT_JOIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// low-res turning
|
|
||||||
|
|
||||||
if (lowres_turn)
|
|
||||||
{
|
|
||||||
static signed short carry = 0;
|
|
||||||
signed short desired_angleturn;
|
|
||||||
|
|
||||||
desired_angleturn = cmd->angleturn + carry;
|
|
||||||
|
|
||||||
// round angleturn to the nearest 256 unit boundary
|
|
||||||
// for recording demos with single byte values for turn
|
|
||||||
|
|
||||||
cmd->angleturn = (desired_angleturn + 128) & 0xff00;
|
|
||||||
|
|
||||||
// Carry forward the error from the reduced resolution to the
|
|
||||||
// next tic, so that successive small movements can accumulate.
|
|
||||||
|
|
||||||
carry = desired_angleturn - cmd->angleturn;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -898,8 +901,9 @@ static void G_DoLoadLevel(void)
|
|||||||
memset (gamekeydown, 0, sizeof(gamekeydown));
|
memset (gamekeydown, 0, sizeof(gamekeydown));
|
||||||
mousex = mousey = 0;
|
mousex = mousey = 0;
|
||||||
memset(&localview, 0, sizeof(localview));
|
memset(&localview, 0, sizeof(localview));
|
||||||
memset(&cmd_carry, 0, sizeof(cmd_carry));
|
memset(&carry, 0, sizeof(carry));
|
||||||
memset(&cmd_prev_carry, 0, sizeof(cmd_prev_carry));
|
memset(&prevcarry, 0, sizeof(prevcarry));
|
||||||
|
memset(&basecmd, 0, sizeof(basecmd));
|
||||||
sendpause = sendsave = paused = false;
|
sendpause = sendsave = paused = false;
|
||||||
// [FG] array size!
|
// [FG] array size!
|
||||||
memset (mousearray, 0, sizeof(mousearray));
|
memset (mousearray, 0, sizeof(mousearray));
|
||||||
@ -970,7 +974,6 @@ static boolean G_StrictModeSkipEvent(event_t *ev)
|
|||||||
{
|
{
|
||||||
first_event = false;
|
first_event = false;
|
||||||
enable_mouse = true;
|
enable_mouse = true;
|
||||||
skip_mouse = false;
|
|
||||||
}
|
}
|
||||||
return !enable_mouse;
|
return !enable_mouse;
|
||||||
|
|
||||||
@ -991,6 +994,23 @@ static boolean G_StrictModeSkipEvent(event_t *ev)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean G_MouseMovementResponder(event_t *ev)
|
||||||
|
{
|
||||||
|
if (G_StrictModeSkipEvent(ev))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev->type == ev_mouse)
|
||||||
|
{
|
||||||
|
mousex += ev->data2;
|
||||||
|
mousey += ev->data3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// G_Responder
|
// G_Responder
|
||||||
// Get info needed to make ticcmd_ts for the players.
|
// Get info needed to make ticcmd_ts for the players.
|
||||||
@ -1105,8 +1125,10 @@ boolean G_Responder(event_t* ev)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_StrictModeSkipEvent(ev))
|
if (G_MouseMovementResponder(ev))
|
||||||
|
{
|
||||||
return true; // eat events
|
return true; // eat events
|
||||||
|
}
|
||||||
|
|
||||||
switch (ev->type)
|
switch (ev->type)
|
||||||
{
|
{
|
||||||
@ -1130,10 +1152,6 @@ boolean G_Responder(event_t* ev)
|
|||||||
mousebuttons[ev->data1] = false;
|
mousebuttons[ev->data1] = false;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case ev_mouse:
|
|
||||||
G_MouseMovementResponder(ev);
|
|
||||||
return true; // eat events
|
|
||||||
|
|
||||||
case ev_joyb_down:
|
case ev_joyb_down:
|
||||||
if (ev->data1 < MAX_JSB)
|
if (ev->data1 < MAX_JSB)
|
||||||
joybuttons[ev->data1] = true;
|
joybuttons[ev->data1] = true;
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
#define MBF21_GAME_OPTION_SIZE (21 + MBF21_COMP_TOTAL)
|
#define MBF21_GAME_OPTION_SIZE (21 + MBF21_COMP_TOTAL)
|
||||||
|
|
||||||
void G_MouseMovementResponder(const event_t *ev);
|
void G_PrepTiccmd(void);
|
||||||
|
boolean G_MouseMovementResponder(event_t *ev);
|
||||||
boolean G_Responder(event_t *ev);
|
boolean G_Responder(event_t *ev);
|
||||||
boolean G_CheckDemoStatus(void);
|
boolean G_CheckDemoStatus(void);
|
||||||
void G_DeathMatchSpawnPlayer(int playernum);
|
void G_DeathMatchSpawnPlayer(int playernum);
|
||||||
|
@ -403,7 +403,6 @@ void I_ReadMouse(void)
|
|||||||
int x, y;
|
int x, y;
|
||||||
static event_t ev;
|
static event_t ev;
|
||||||
|
|
||||||
SDL_PumpEvents();
|
|
||||||
SDL_GetRelativeMouseState(&x, &y);
|
SDL_GetRelativeMouseState(&x, &y);
|
||||||
|
|
||||||
if (x != 0 || y != 0)
|
if (x != 0 || y != 0)
|
||||||
|
@ -45,6 +45,8 @@ void I_StartFrame (void);
|
|||||||
|
|
||||||
void I_StartTic (void);
|
void I_StartTic (void);
|
||||||
|
|
||||||
|
void I_StartDisplay(void);
|
||||||
|
|
||||||
// Asynchronous interrupt functions should maintain private queues
|
// Asynchronous interrupt functions should maintain private queues
|
||||||
// that are read by the synchronous functions
|
// that are read by the synchronous functions
|
||||||
// to be converted into events.
|
// to be converted into events.
|
||||||
|
@ -418,15 +418,25 @@ static void I_GetEvent(void)
|
|||||||
//
|
//
|
||||||
void I_StartTic (void)
|
void I_StartTic (void)
|
||||||
{
|
{
|
||||||
|
I_GetEvent();
|
||||||
|
|
||||||
if (window_focused)
|
if (window_focused)
|
||||||
{
|
{
|
||||||
I_ReadMouse();
|
I_ReadMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
I_GetEvent();
|
|
||||||
I_UpdateJoystick();
|
I_UpdateJoystick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_StartDisplay(void)
|
||||||
|
{
|
||||||
|
if (window_focused)
|
||||||
|
{
|
||||||
|
SDL_PumpEvents();
|
||||||
|
I_ReadMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// I_StartFrame
|
// I_StartFrame
|
||||||
//
|
//
|
||||||
|
@ -3941,6 +3941,7 @@ enum {
|
|||||||
gen5_mouse3,
|
gen5_mouse3,
|
||||||
gen5_mouse_accel,
|
gen5_mouse_accel,
|
||||||
gen5_mouse_accel_threshold,
|
gen5_mouse_accel_threshold,
|
||||||
|
gen5_mouse_raw_input,
|
||||||
gen5_end1,
|
gen5_end1,
|
||||||
|
|
||||||
gen5_title2,
|
gen5_title2,
|
||||||
@ -4165,6 +4166,9 @@ setup_menu_t gen_settings5[] = { // General Settings screen5
|
|||||||
{"Mouse threshold", S_NUM, m_null, M_X,
|
{"Mouse threshold", S_NUM, m_null, M_X,
|
||||||
M_Y + gen5_mouse_accel_threshold * M_SPC, {"mouse_acceleration_threshold"}},
|
M_Y + gen5_mouse_accel_threshold * M_SPC, {"mouse_acceleration_threshold"}},
|
||||||
|
|
||||||
|
{"Raw mouse input", S_YESNO, m_null, M_X,
|
||||||
|
M_Y+ gen5_mouse_raw_input * M_SPC, {"mouse_raw_input"}},
|
||||||
|
|
||||||
{"", S_SKIP, m_null, M_X, M_Y + gen5_end1*M_SPC},
|
{"", S_SKIP, m_null, M_X, M_Y + gen5_end1*M_SPC},
|
||||||
|
|
||||||
{"Miscellaneous" ,S_SKIP|S_TITLE, m_null, M_X, M_Y + gen5_title2*M_SPC},
|
{"Miscellaneous" ,S_SKIP|S_TITLE, m_null, M_X, M_Y + gen5_title2*M_SPC},
|
||||||
|
@ -2059,6 +2059,13 @@ default_t defaults[] = {
|
|||||||
"adjust mouse acceleration threshold"
|
"adjust mouse acceleration threshold"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"mouse_raw_input",
|
||||||
|
(config_t *) &mouse_raw_input, NULL,
|
||||||
|
{1}, {0, 1}, number, ss_none, wad_no,
|
||||||
|
"Raw mouse input for turning/looking (0 = Interpolate, 1 = Raw)"
|
||||||
|
},
|
||||||
|
|
||||||
// [FG] invert vertical axis
|
// [FG] invert vertical axis
|
||||||
{
|
{
|
||||||
"mouse_y_invert",
|
"mouse_y_invert",
|
||||||
|
17
src/p_user.c
17
src/p_user.c
@ -190,6 +190,12 @@ 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;
|
||||||
|
|
||||||
|
if (player == &players[consoleplayer])
|
||||||
|
{
|
||||||
|
localview.ticangle += localview.ticangleturn << 16;
|
||||||
|
localview.ticangleturn = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// killough 10/98:
|
// killough 10/98:
|
||||||
//
|
//
|
||||||
// We must apply thrust to the player and bobbing separately, to avoid
|
// We must apply thrust to the player and bobbing separately, to avoid
|
||||||
@ -353,6 +359,11 @@ void P_PlayerThink (player_t* player)
|
|||||||
player->oldlookdir = player->lookdir;
|
player->oldlookdir = player->lookdir;
|
||||||
player->oldrecoilpitch = player->recoilpitch;
|
player->oldrecoilpitch = player->recoilpitch;
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
@ -386,7 +397,11 @@ void P_PlayerThink (player_t* player)
|
|||||||
if (abs(player->lookdir) < 8 * MLOOKUNIT)
|
if (abs(player->lookdir) < 8 * MLOOKUNIT)
|
||||||
{
|
{
|
||||||
player->lookdir = 0;
|
player->lookdir = 0;
|
||||||
player->centering = false;
|
|
||||||
|
if (player->oldlookdir == 0)
|
||||||
|
{
|
||||||
|
player->centering = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player->slope = PLAYER_SLOPE(player);
|
player->slope = PLAYER_SLOPE(player);
|
||||||
|
33
src/r_main.c
33
src/r_main.c
@ -48,6 +48,7 @@ fixed_t projection;
|
|||||||
fixed_t viewx, viewy, viewz;
|
fixed_t viewx, viewy, viewz;
|
||||||
angle_t viewangle;
|
angle_t viewangle;
|
||||||
localview_t localview;
|
localview_t localview;
|
||||||
|
boolean mouse_raw_input;
|
||||||
fixed_t viewcos, viewsin;
|
fixed_t viewcos, viewsin;
|
||||||
player_t *viewplayer;
|
player_t *viewplayer;
|
||||||
extern lighttable_t **walllights;
|
extern lighttable_t **walllights;
|
||||||
@ -648,10 +649,12 @@ void R_SetupFrame (player_t *player)
|
|||||||
leveltime > oldleveltime)
|
leveltime > oldleveltime)
|
||||||
{
|
{
|
||||||
const boolean use_localview = (
|
const boolean use_localview = (
|
||||||
|
// Don't use localview when interpolation is preferred.
|
||||||
|
mouse_raw_input &&
|
||||||
// Don't use localview if the player is spying.
|
// Don't use localview if the player is spying.
|
||||||
player == &players[consoleplayer] &&
|
player == &players[consoleplayer] &&
|
||||||
// Don't use localview if the player is dead.
|
// Don't use localview if the player is dead.
|
||||||
player->health > 0 &&
|
player->playerstate != PST_DEAD &&
|
||||||
// Don't use localview if the player just teleported.
|
// Don't use localview if the player just teleported.
|
||||||
!player->mo->reactiontime &&
|
!player->mo->reactiontime &&
|
||||||
// Don't use localview if a demo is playing.
|
// Don't use localview if a demo is playing.
|
||||||
@ -667,12 +670,16 @@ void R_SetupFrame (player_t *player)
|
|||||||
|
|
||||||
// Use localview unless the player or game is in an invalid state or if
|
// Use localview unless the player or game is in an invalid state or if
|
||||||
// mouse input was interrupted, in which case fall back to interpolation.
|
// mouse input was interrupted, in which case fall back to interpolation.
|
||||||
if (localview.useangle && use_localview)
|
if (use_localview)
|
||||||
viewangle = player->mo->angle - ((short)localview.angle << FRACBITS) + viewangleoffset;
|
{
|
||||||
|
viewangle = (player->mo->angle + localview.angle - localview.ticangle +
|
||||||
|
R_InterpolateAngle(localview.oldticangle, localview.ticangle,
|
||||||
|
fractionaltic));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
viewangle = R_InterpolateAngle(player->mo->oldangle, player->mo->angle, fractionaltic) + viewangleoffset;
|
viewangle = R_InterpolateAngle(player->mo->oldangle, player->mo->angle, fractionaltic);
|
||||||
|
|
||||||
if (localview.usepitch && use_localview && !player->centering && player->lookdir)
|
if (localview.usepitch && use_localview && !player->centering)
|
||||||
pitch = (player->lookdir + localview.pitch) / MLOOKUNIT;
|
pitch = (player->lookdir + localview.pitch) / MLOOKUNIT;
|
||||||
else
|
else
|
||||||
pitch = (player->oldlookdir + (player->lookdir - player->oldlookdir) * FIXED2DOUBLE(fractionaltic)) / MLOOKUNIT;
|
pitch = (player->oldlookdir + (player->lookdir - player->oldlookdir) * FIXED2DOUBLE(fractionaltic)) / MLOOKUNIT;
|
||||||
@ -682,13 +689,17 @@ void R_SetupFrame (player_t *player)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
viewx = player->mo->x;
|
viewx = player->mo->x;
|
||||||
viewy = player->mo->y;
|
viewy = player->mo->y;
|
||||||
viewz = player->viewz; // [FG] moved here
|
viewz = player->viewz; // [FG] moved here
|
||||||
viewangle = player->mo->angle + viewangleoffset;
|
viewangle = player->mo->angle;
|
||||||
// [crispy] pitch is actual lookdir and weapon pitch
|
// [crispy] pitch is actual lookdir and weapon pitch
|
||||||
pitch = player->lookdir / MLOOKUNIT + player->recoilpitch;
|
pitch = player->lookdir / MLOOKUNIT + player->recoilpitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3-screen display mode.
|
||||||
|
viewangle += viewangleoffset;
|
||||||
|
|
||||||
extralight = player->extralight;
|
extralight = player->extralight;
|
||||||
extralight += STRICTMODE(LIGHTBRIGHT * extra_level_brightness);
|
extralight += STRICTMODE(LIGHTBRIGHT * extra_level_brightness);
|
||||||
|
|
||||||
|
@ -81,6 +81,8 @@ extern lighttable_t *fixedcolormap;
|
|||||||
// range of [0.0, 1.0). Used for interpolation.
|
// range of [0.0, 1.0). Used for interpolation.
|
||||||
extern fixed_t fractionaltic;
|
extern fixed_t fractionaltic;
|
||||||
|
|
||||||
|
extern boolean mouse_raw_input;
|
||||||
|
|
||||||
// [AM] Interpolate between two angles.
|
// [AM] Interpolate between two angles.
|
||||||
angle_t R_InterpolateAngle(angle_t oangle, angle_t nangle, fixed_t scale);
|
angle_t R_InterpolateAngle(angle_t oangle, angle_t nangle, fixed_t scale);
|
||||||
|
|
||||||
|
@ -90,8 +90,11 @@ extern side_t *sides;
|
|||||||
|
|
||||||
typedef struct localview_s
|
typedef struct localview_s
|
||||||
{
|
{
|
||||||
boolean useangle;
|
|
||||||
boolean usepitch;
|
boolean usepitch;
|
||||||
|
angle_t oldticangle;
|
||||||
|
angle_t ticangle;
|
||||||
|
int ticangleturn;
|
||||||
|
double rawangle;
|
||||||
int angle;
|
int angle;
|
||||||
int pitch;
|
int pitch;
|
||||||
} localview_t;
|
} localview_t;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user