From 8c723f52d16c0b8890b0077a2dcb3692ee1a1332 Mon Sep 17 00:00:00 2001 From: Mitchell Richters Date: Wed, 24 Jun 2020 23:11:42 +1000 Subject: [PATCH] - make controller input identical across all games. * Convert axes in ControlInfo struct from int32_t to float as what's received from the backend. * Remove all the scale up/down math since we don't need that with floats and replace with float constants that match old behaviour. * Store q16mlook scaling as a constant for use with mouse and upcoming controller code. * Add required controller code to Blood as the only game not to have working controllers. * Fix typos in (gInput.forward > input.forward) for `ctrlGetInput()` in Blood. * Remove use of `scaleAdjustmentToInterval()` on Exhumed and Shadow Warrior as they only process forward/side velocities within the game's ticrate. * Repair angvel/aimvel scaling mistakes from d79a5d256d7593a3633759f302ebc33cc7710ecb. * Scale dyaw and dpitch by 25% for Shadow Warrior as the game runs 25% faster than the other games, leading to faster input. --- source/blood/src/controls.cpp | 33 +++++++++++++++++++++----------- source/core/inputstate.cpp | 8 ++++---- source/core/inputstate.h | 15 ++++++--------- source/duke3d/src/player.cpp | 11 +++++------ source/exhumed/src/player.cpp | 11 +++++------ source/rr/src/player.cpp | 36 ++++++++++++++++------------------- source/sw/src/game.cpp | 21 ++++++++++++-------- source/sw/src/player.cpp | 6 +++--- 8 files changed, 74 insertions(+), 67 deletions(-) diff --git a/source/blood/src/controls.cpp b/source/blood/src/controls.cpp index f86948cc6..8734507be 100644 --- a/source/blood/src/controls.cpp +++ b/source/blood/src/controls.cpp @@ -306,10 +306,10 @@ void ctrlGetInput(void) if (gInput.forward < keyMove && gInput.forward > -keyMove) { if (buttonMap.ButtonDown(gamefunc_Move_Forward)) - gInput.forward += keyMove; + input.forward += keyMove; if (buttonMap.ButtonDown(gamefunc_Move_Backward)) - gInput.forward -= keyMove; + input.forward -= keyMove; } if (gInput.strafe < keyMove && gInput.strafe > -keyMove) @@ -345,6 +345,10 @@ void ctrlGetInput(void) static int32_t lastInputClock; // MED int32_t const elapsedTics = (int32_t)totalclock - lastInputClock; + // Blood's q16mlook scaling is different from the other games, therefore use the below constant to attenuate + // the speed to match the other games. + float const mlookScale = 3.25f; + lastInputClock = (int32_t) totalclock; if (turnLeft || turnRight) @@ -361,25 +365,32 @@ void ctrlGetInput(void) input.q16turn <<= 1; if (buttonMap.ButtonDown(gamefunc_Strafe)) - input.strafe -= info.mousex; + { + static int strafeyaw; + + input.strafe = -(info.mousex + strafeyaw) >> 3; + strafeyaw = (info.mousex + strafeyaw) % 8; + + input.strafe -= scaleAdjustmentToInterval(info.dyaw * keyMove); + } else + { input.q16turn = fix16_sadd(input.q16turn, fix16_sdiv(fix16_from_int(info.mousex), fix16_from_int(32))); + input.q16turn = fix16_sadd(input.q16turn, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); + } - input.strafe -= -(info.dx<<5); + input.strafe -= scaleAdjustmentToInterval(info.dx * keyMove); + input.forward -= scaleAdjustmentToInterval(info.dz * keyMove); -#if 0 - if (info.dz < 0) - gInput.mlook = ClipRange((info.dz+127)>>7, -127, 127); - else - gInput.mlook = ClipRange(info.dz>>7, -127, 127); -#endif if (mouseaim) - input.q16mlook = fix16_sadd(input.q16mlook, fix16_sdiv(fix16_from_int(info.mousey), fix16_from_int(208))); + input.q16mlook = fix16_sadd(input.q16mlook, fix16_sdiv(fix16_from_int(info.mousey), fix16_from_float(mlookScale * 64.f))); else input.forward -= info.mousey; if (!in_mouseflip) input.q16mlook = -input.q16mlook; + input.q16mlook = fix16_ssub(input.q16mlook, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch / mlookScale))); + if (!gViewMap.bFollowMode && gViewMode == 4) { gViewMap.turn += input.q16turn<<2; diff --git a/source/core/inputstate.cpp b/source/core/inputstate.cpp index 7df21cad6..0bac2c696 100644 --- a/source/core/inputstate.cpp +++ b/source/core/inputstate.cpp @@ -195,9 +195,9 @@ void CONTROL_GetInput(ControlInfo* info) I_GetAxes(joyaxes); - info->dyaw += -joyaxes[JOYAXIS_Yaw] * joyaxesScale; - info->dx += -joyaxes[JOYAXIS_Side] * joyaxesScale; - info->dz += -joyaxes[JOYAXIS_Forward] * joyaxesScale; - info->dpitch += -joyaxes[JOYAXIS_Pitch] * joyaxesScale; + info->dyaw += -joyaxes[JOYAXIS_Yaw] * 45.f; + info->dx += -joyaxes[JOYAXIS_Side] * 0.75f; + info->dz += -joyaxes[JOYAXIS_Forward] * 0.75f; + info->dpitch += -joyaxes[JOYAXIS_Pitch] * 22.5f; } } diff --git a/source/core/inputstate.h b/source/core/inputstate.h index f61b75305..9d5bcd922 100644 --- a/source/core/inputstate.h +++ b/source/core/inputstate.h @@ -15,12 +15,12 @@ typedef uint16_t kb_scancode; struct ControlInfo { - int32_t dx; - int32_t dy; - int32_t dz; - int32_t dyaw; - int32_t dpitch; - int32_t droll; + float dx; + float dy; + float dz; + float dyaw; + float dpitch; + float droll; int32_t mousex; int32_t mousey; }; @@ -179,9 +179,6 @@ public: extern InputState inputState; -const int analogExtent = 32767; // used as a divisor for scaling joystick input. -const float joyaxesScale = (float)analogExtent * 0.75f; // used as a multiplier for scaling joystick input. - void CONTROL_GetInput(ControlInfo* info); int32_t handleevents(void); diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index a174c03d2..f3462d1ac 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -3084,7 +3084,6 @@ void P_GetInput(int const playerNum) // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN; - constexpr int analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; input_t input {}; @@ -3096,12 +3095,12 @@ void P_GetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); } if (mouseaim) @@ -3111,9 +3110,9 @@ void P_GetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); - input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove); if (buttonMap.ButtonDown(gamefunc_Strafe)) { diff --git a/source/exhumed/src/player.cpp b/source/exhumed/src/player.cpp index 53195a3c6..8c6cab0ba 100644 --- a/source/exhumed/src/player.cpp +++ b/source/exhumed/src/player.cpp @@ -188,7 +188,6 @@ void PlayerInterruptKeys() int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int const turnAmount = playerRunning ? 12 : 8; int const keyMove = playerRunning ? 12 : 6; - int const analogTurnAmount = 12; if (buttonMap.ButtonDown(gamefunc_Strafe)) { @@ -197,12 +196,12 @@ void PlayerInterruptKeys() input.xVel = -(info.mousex + strafeyaw) >> 6; strafeyaw = (info.mousex + strafeyaw) % 64; - input.xVel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); + input.xVel -= info.dyaw * keyMove; } else { input.nAngle = fix16_sadd(input.nAngle, fix16_sdiv(fix16_from_int(info.mousex), fix16_from_int(32))); - input.nAngle = fix16_sadd(input.nAngle, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.nAngle = fix16_sadd(input.nAngle, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); } g_MyAimMode = in_mousemode || buttonMap.ButtonDown(gamefunc_Mouse_Aiming); @@ -214,9 +213,9 @@ void PlayerInterruptKeys() if (!in_mouseflip) input.horizon = -input.horizon; - input.horizon = fix16_ssub(input.horizon, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); - input.xVel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.yVel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.horizon = fix16_ssub(input.horizon, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch))); + input.xVel -= info.dx * keyMove; + input.yVel -= info.dz * keyMove; if (buttonMap.ButtonDown(gamefunc_Strafe)) { diff --git a/source/rr/src/player.cpp b/source/rr/src/player.cpp index 6a15e5529..768cab4ca 100644 --- a/source/rr/src/player.cpp +++ b/source/rr/src/player.cpp @@ -3254,7 +3254,6 @@ void P_GetInput(int const playerNum) int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); int const turnAmount = playerRunning ? (NORMALTURN << 1) : NORMALTURN; - int const analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; input_t input {}; @@ -3266,12 +3265,12 @@ void P_GetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); } if (mouseaim) @@ -3281,9 +3280,9 @@ void P_GetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); - input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove); if (buttonMap.ButtonDown(gamefunc_Strafe)) { @@ -3668,16 +3667,15 @@ void P_GetInputMotorcycle(int playerNum) // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); - int const analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; input_t input {}; input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); - input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove); pPlayer->crouch_toggle = 0; @@ -3918,16 +3916,15 @@ void P_GetInputBoat(int playerNum) // JBF: Run key behaviour is selectable int const playerRunning = G_CheckAutorun(buttonMap.ButtonDown(gamefunc_Run)); - int const analogTurnAmount = (NORMALTURN << 1); int const keyMove = playerRunning ? (NORMALKEYMOVE << 1) : NORMALKEYMOVE; input_t input {}; input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); - input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove); pPlayer->crouch_toggle = 0; @@ -4159,7 +4156,6 @@ void P_DHGetInput(int const playerNum) int const playerCrouch = sub_299D8(); int const playerJump = buttonMap.ButtonDown(gamefunc_Jump) && !(pPlayer->cursectnum >= 0 && sector[pPlayer->cursectnum].hitag == 2003); int const turnAmount = playerCrouch ? 2 : (playerRunning ? 16 : 8); - int const analogTurnAmount = 16; int const keyMove = playerCrouch ? 3 : (playerRunning ? 24 : 12); input_t input {}; @@ -4171,12 +4167,12 @@ void P_DHGetInput(int const playerNum) input.svel = -(info.mousex + strafeyaw) >> 3; strafeyaw = (info.mousex + strafeyaw) % 8; - input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove / analogExtent); + input.svel -= scaleAdjustmentToInterval(info.dyaw * keyMove); } else { input.q16avel = fix16_sadd(input.q16avel, fix16_sdiv(fix16_from_int(info.mousex), F16(32))); - input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * analogTurnAmount / (analogExtent >> 1)))); + input.q16avel = fix16_sadd(input.q16avel, fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw))); } if (mouseaim) @@ -4186,9 +4182,9 @@ void P_DHGetInput(int const playerNum) if (!in_mouseflip) input.q16horz = -input.q16horz; - input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * analogTurnAmount / analogExtent))); - input.svel -= scaleAdjustmentToInterval(info.dx * keyMove / analogExtent); - input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove / analogExtent); + input.q16horz = fix16_ssub(input.q16horz, fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch))); + input.svel -= scaleAdjustmentToInterval(info.dx * keyMove); + input.fvel -= scaleAdjustmentToInterval(info.dz * keyMove); auto scaleAdjustmentToInterval = [=](double x) { return x * REALGAMETICSPERSEC / (1000.0 / elapsedInputTicks); }; diff --git a/source/sw/src/game.cpp b/source/sw/src/game.cpp index ded2a330c..5a96d3031 100644 --- a/source/sw/src/game.cpp +++ b/source/sw/src/game.cpp @@ -2996,7 +2996,12 @@ getinput(SW_PACKET *loc, SWBOOL tied) // The function DoPlayerTurn() scales the player's q16angvel by 1.40625, so store as constant // and use to scale back player's aim and ang values for a consistent feel between games. - float const inputScale = 1.40625f; + float const angvelScale = 1.40625f; + float const aimvelScale = 1.203125f; + + // Shadow Warrior has a ticrate of 40, 25% more than the other games, so store below constant + // for dividing controller input to match speed input speed of other games. + float const ticrateScale = 0.75f; if (running) { @@ -3026,25 +3031,25 @@ getinput(SW_PACKET *loc, SWBOOL tied) if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop) { svel = -info.mousex; - svel -= scaleAdjustmentToInterval(info.dyaw * keymove / analogExtent); + svel -= info.dyaw * keymove; } else { - q16angvel = fix16_div(fix16_from_int(info.mousex), fix16_from_int(inputScale * 32)); - q16angvel += fix16_from_dbl(scaleAdjustmentToInterval(info.dyaw * turnamount / (inputScale * (analogExtent >> 1)))); + q16angvel = fix16_div(fix16_from_int(info.mousex), fix16_from_float(angvelScale * 32.f)); + q16angvel += fix16_from_dbl(scaleAdjustmentToInterval((info.dyaw * ticrateScale) / angvelScale)); } if (mouseaim) - q16aimvel = -fix16_div(fix16_from_int(info.mousey), fix16_from_int((inputScale / 2) * 64)); + q16aimvel = -fix16_div(fix16_from_int(info.mousey), fix16_from_float(aimvelScale * 64.f)); else vel = -(info.mousey >> 6); if (in_mouseflip) q16aimvel = -q16aimvel; - q16aimvel -= fix16_from_dbl(scaleAdjustmentToInterval(info.dpitch * turnamount / ((inputScale / 2) * analogExtent))); - svel -= scaleAdjustmentToInterval(info.dx * keymove / analogExtent); - vel -= scaleAdjustmentToInterval(info.dz * keymove / analogExtent); + q16aimvel -= fix16_from_dbl(scaleAdjustmentToInterval((info.dpitch * ticrateScale) / aimvelScale)); + svel -= info.dx * keymove; + vel -= info.dz * keymove; if (buttonMap.ButtonDown(gamefunc_Strafe) && !pp->sop) { diff --git a/source/sw/src/player.cpp b/source/sw/src/player.cpp index ff1e8f13d..c596bc024 100644 --- a/source/sw/src/player.cpp +++ b/source/sw/src/player.cpp @@ -2531,9 +2531,9 @@ MoveScrollMode2D(PLAYERp pp) } if (buttonMap.ButtonDown(gamefunc_Strafe)) - mfsvel -= scrl_input.dyaw>>2; - mfsvel -= scrl_input.dx>>2; - mfvel = -scrl_input.dz>>2; + mfsvel -= scrl_input.dyaw / 4; + mfsvel -= scrl_input.dx / 4; + mfvel = -scrl_input.dz /4; #if 0 int const running = !!BUTTON(gamefunc_Run) ^ !!TEST(pp->Flags, PF_LOCK_RUN);