From e827bdcc5b2316e2ae92378c0888322cdd0be285 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Fri, 12 Dec 2025 21:31:53 -0500 Subject: [PATCH] Add per-type deadzone support --- src/d_main.cpp | 2 +- src/d_netcmd.c | 4 +- src/g_game.c | 119 ++++++++++++++++++++++++++++++++++++------------- src/g_game.h | 17 +++++-- src/hu_stuff.c | 2 +- src/m_menu.c | 4 +- src/p_tick.c | 2 +- src/y_inter.c | 12 ++--- 8 files changed, 117 insertions(+), 45 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index e58f62ff8..6d9c1ce29 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -93,7 +93,7 @@ #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291 #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9 -#define ASSET_HASH_MAIN_PK3 0x691ecab859221089 +#define ASSET_HASH_MAIN_PK3 0xb359aca95ab7d254 #define ASSET_HASH_MAPPATCH_PK3 0x73e09e7e291c7cc7 #define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461 #ifdef USE_PATCH_FILE diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 18b1e6980..3ceb00a64 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1295,7 +1295,9 @@ void D_RegisterClientCommands(void) { CV_RegisterVar(&cv_kickstartaccel[i]); CV_RegisterVar(&cv_shrinkme[i]); - CV_RegisterVar(&cv_deadzone[i]); + CV_RegisterVar(&cv_deadzonex[i]); + CV_RegisterVar(&cv_deadzoney[i]); + CV_RegisterVar(&cv_deadzonet[i]); CV_RegisterVar(&cv_deadzonestyle[i]); CV_RegisterVar(&cv_litesteer[i]); CV_RegisterVar(&cv_turnsmooth[i]); diff --git a/src/g_game.c b/src/g_game.c index 51cbf835a..e1aa1d5ce 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -465,11 +465,24 @@ consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS] = { }; static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; -consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("deadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("deadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("deadzone3", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), - CVAR_INIT ("deadzone4", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) +consvar_t cv_deadzonex[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("xdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("xdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("xdeadzone3", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("xdeadzone4", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) +}; +consvar_t cv_deadzoney[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("ydeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("ydeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("ydeadzone3", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("ydeadzone4", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) +}; + +consvar_t cv_deadzonet[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("tdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("tdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("tdeadzone3", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("tdeadzone4", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) }; static CV_PossibleValue_t deadzonestyle_cons_t[] = {{0, "Kart"}, {1, "RR"}, {0, NULL}}; @@ -1152,7 +1165,9 @@ void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox) // returns true if event's axis is within the deadzone for the given player boolean G_AxisInDeadzone(UINT8 p, event_t *ev) { - return abs(ev->data2) <= (JOYAXISRANGE * cv_deadzone[p].value) / FRACUNIT; + fixed_t deadzonetype = G_GetDeadZoneType(p, G_GetAxisTypeForData1(ev->data1)); + // Lets make button default.... + return abs(ev->data2) <= (JOYAXISRANGE * deadzonetype) / FRACUNIT; } // check if the given key is bound to the given gamecontrol @@ -1181,7 +1196,44 @@ bound: return false; } -INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital) +SINT8 G_GetAxisTypeForData1(SINT8 data1) +{ + switch (data1) + { + case 0: + case 2: + return DEADZONE_X; + break; + case 1: + case 3: + return DEADZONE_Y; + break; + case 4: + case 5: + default: + return DEADZONE_BUTTON; + break; + } +} + +fixed_t G_GetDeadZoneType(INT32 p, SINT8 type) +{ + switch (type) + { + case DEADZONE_X: + return cv_deadzonex[p].value; + break; + case DEADZONE_Y: + return cv_deadzoney[p].value; + break; + case DEADZONE_BUTTON: + default: + return cv_deadzonet[p].value; + break; + } +} + +INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital, SINT8 type) { INT32 deviceID; INT32 i; @@ -1195,7 +1247,9 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital) return 0; } - deadzone = (JOYAXISRANGE * cv_deadzone[p].value) / FRACUNIT; + fixed_t deadzonetype = G_GetDeadZoneType(p,type); + + deadzone = (JOYAXISRANGE * deadzonetype) / FRACUNIT; deviceID = I_GetJoystickDeviceIndexForPlayer(p) + 1; @@ -1229,9 +1283,9 @@ retrygetcontrol: return 0; } -boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital) +boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital, SINT8 type) { - return (G_PlayerInputAnalog(p, gc, digital) != 0); + return (G_PlayerInputAnalog(p, gc, digital, type) != 0); } // Take a magnitude of two axes, and adjust it to take out the deadzone @@ -1260,7 +1314,8 @@ static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone) static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector) { INT32 gamepadStyle = Joystick[splitnum].bGamepadStyle; - fixed_t deadZone = cv_deadzone[splitnum].value; + fixed_t deadZoneX = cv_deadzonex[splitnum].value; + fixed_t deadZoneY = cv_deadzoney[splitnum].value; SINT8 deadZoneStyle = cv_deadzonestyle[splitnum].value; // When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code. @@ -1276,7 +1331,8 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis); INT32 normalisedXAxis; INT32 normalisedYAxis; - INT32 normalisedMagnitude; + INT32 normalisedMagnitudeX; + INT32 normalisedMagnitudeY; double dMagnitude = sqrt((double)magnitude); magnitude = (INT32)dMagnitude; @@ -1285,11 +1341,12 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE; // Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE - normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone); + normalisedMagnitudeX = G_BasicDeadZoneCalculation(magnitude, deadZoneX); + normalisedMagnitudeY = G_BasicDeadZoneCalculation(magnitude, deadZoneY); // Apply the deadzone to the xy axes - joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE; - joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE; + joystickvector->xaxis = (normalisedXAxis * normalisedMagnitudeX) / JOYAXISRANGE; + joystickvector->yaxis = (normalisedYAxis * normalisedMagnitudeY) / JOYAXISRANGE; // Cap the values so they don't go above the correct maximum joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE); @@ -1371,7 +1428,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) return; } - joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_turnright, false) - G_PlayerInputAnalog(forplayer, gc_turnleft, false); + joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_turnright, false, DEADZONE_X) - G_PlayerInputAnalog(forplayer, gc_turnleft, false, DEADZONE_X); joystickvector.yaxis = 0; G_HandleAxisDeadZone(forplayer, &joystickvector); @@ -1379,7 +1436,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // use it for aiming to throw items forward/backward and the vote screen // This mean that the turn axis will still be gradient but up/down will be 0 // until the stick is pushed far enough - joystickvector.yaxis = G_PlayerInputAnalog(forplayer, gc_aimbackward, false) - G_PlayerInputAnalog(forplayer, gc_aimforward, false); + joystickvector.yaxis = G_PlayerInputAnalog(forplayer, gc_aimbackward, false, DEADZONE_Y) - G_PlayerInputAnalog(forplayer, gc_aimforward, false, DEADZONE_Y); if (encoremode) { @@ -1399,7 +1456,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { // check turn input again, but this time digital only // if it's false, an analog stick is inputting the turn; no smoothing! - if (G_PlayerInputDown(forplayer, gc_turnleft, true) || G_PlayerInputDown(forplayer, gc_turnright, true)) + if (G_PlayerInputDown(forplayer, gc_turnleft, true, DEADZONE_X) || G_PlayerInputDown(forplayer, gc_turnright, true, DEADZONE_X)) { I_Assert(cv_turnsmooth[forplayer].value); tspeed /= cv_turnsmooth[forplayer].value * 2; @@ -1441,12 +1498,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (spectating || objectplacing) // SRB2Kart: spectators need special controls { - if (G_PlayerInputDown(forplayer, gc_accelerate, false)) + if (G_PlayerInputDown(forplayer, gc_accelerate, false, DEADZONE_BUTTON)) { cmd->buttons |= BT_ACCELERATE; } - if (G_PlayerInputDown(forplayer, gc_brake, false)) + if (G_PlayerInputDown(forplayer, gc_brake, false, DEADZONE_BUTTON)) { cmd->buttons |= BT_BRAKE; } @@ -1464,7 +1521,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. - fixed_t value = G_PlayerInputAnalog(forplayer, gc_accelerate, false); + fixed_t value = G_PlayerInputAnalog(forplayer, gc_accelerate, false, DEADZONE_BUTTON); if (value != 0) { cmd->buttons |= BT_ACCELERATE; @@ -1474,7 +1531,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (player->sneakertimer) forward = MAXPLMOVE; // 50 - value = G_PlayerInputAnalog(forplayer, gc_brake, false); + value = G_PlayerInputAnalog(forplayer, gc_brake, false, DEADZONE_BUTTON); if (value != 0) { cmd->buttons |= BT_BRAKE; @@ -1490,33 +1547,33 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } // fire with any button/key - if (G_PlayerInputDown(forplayer, gc_fire, false)) + if (G_PlayerInputDown(forplayer, gc_fire, false, DEADZONE_BUTTON)) { cmd->buttons |= BT_ATTACK; } // drift with any button/key - if (G_PlayerInputDown(forplayer, gc_drift, false)) + if (G_PlayerInputDown(forplayer, gc_drift, false, DEADZONE_BUTTON)) { cmd->buttons |= BT_DRIFT; } // rear view with any button/key - if (G_PlayerInputDown(forplayer, gc_lookback, false)) + if (G_PlayerInputDown(forplayer, gc_lookback, false, DEADZONE_BUTTON)) { cmd->buttons |= BT_LOOKBACK; } // Lua scriptable buttons - if (G_PlayerInputDown(forplayer, gc_custom1, false)) + if (G_PlayerInputDown(forplayer, gc_custom1, false, DEADZONE_BUTTON)) cmd->buttons |= BT_CUSTOM1; - if (G_PlayerInputDown(forplayer, gc_custom2, false)) + if (G_PlayerInputDown(forplayer, gc_custom2, false, DEADZONE_BUTTON)) cmd->buttons |= BT_CUSTOM2; - if (G_PlayerInputDown(forplayer, gc_custom3, false)) + if (G_PlayerInputDown(forplayer, gc_custom3, false, DEADZONE_BUTTON)) cmd->buttons |= BT_CUSTOM3; // Reset camera - if (G_PlayerInputDown(forplayer, gc_camreset, false)) + if (G_PlayerInputDown(forplayer, gc_camreset, false, DEADZONE_BUTTON)) { if (thiscam->chase && *rd == false) P_ResetCamera(player, thiscam); @@ -1532,7 +1589,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) && (!thiscam->chase)) //because chasecam's not inverted ? -1 : 1; // set to -1 or 1 to multiply - INT32 axis = G_PlayerInputAnalog(forplayer, gc_lookup, false) - G_PlayerInputAnalog(forplayer, gc_lookdown, false); + INT32 axis = G_PlayerInputAnalog(forplayer, gc_lookup, false, DEADZONE_Y) - G_PlayerInputAnalog(forplayer, gc_lookdown, false, DEADZONE_Y); // either i allow mouse binds in controls... or i just hardcode it :^) INT32 mousey = gamekeydown[0][KEY_MOUSEMOVE+1] - gamekeydown[0][KEY_MOUSEMOVE+0]; @@ -1541,7 +1598,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (axis != 0 && spectating) cmd->aiming += axis/2 * screen_invert; // divide by 2 to match KB_LOOKSPEED - if (G_PlayerInputDown(forplayer, gc_centerview, false)) // // No need to put a spectator limit on this one though :V + if (G_PlayerInputDown(forplayer, gc_centerview, false, DEADZONE_BUTTON)) // // No need to put a spectator limit on this one though :V cmd->aiming = 0; } diff --git a/src/g_game.h b/src/g_game.h index 6a42a0fee..b1d9a28d8 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -81,7 +81,9 @@ extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_jitterlegacy[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_deadzonex[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_deadzoney[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_deadzonet[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzonestyle[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; @@ -123,9 +125,18 @@ void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox); extern angle_t localangle[MAXSPLITSCREENPLAYERS]; extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed -INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital); -boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital); +typedef enum +{ + DEADZONE_X, + DEADZONE_Y, + DEADZONE_BUTTON, +} analogdeadzone_e; + +fixed_t G_GetDeadZoneType(INT32 p, SINT8 type); +INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital, SINT8 type); +boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital, SINT8 type); boolean G_ControlBoundToKey(UINT8 p, INT32 gc, INT32 key, boolean defaults); +SINT8 G_GetAxisTypeForData1(SINT8 data1); boolean G_AxisInDeadzone(UINT8 p, event_t *ev); // diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 9466e9c41..e438a1261 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -987,7 +987,7 @@ void HU_Ticker(void) hu_emoteanim++; hu_tick &= 7; // currently only to blink chat input cursor - if (G_PlayerInputDown(0, gc_scores, false)) + if (G_PlayerInputDown(0, gc_scores, false, DEADZONE_BUTTON)) hu_showscores = !chat_on; else hu_showscores = false; diff --git a/src/m_menu.c b/src/m_menu.c index edf537818..8d6952e84 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8616,7 +8616,9 @@ INT32 MR_SetupControlsMenu(INT32 arg) // Set proper gamepad options M_SetItemArgument(MN_OP_CHANGECONTROLS, "SETJOY", arg); - M_SetItemCvar(MN_OP_CHANGECONTROLS, "DEADZ", &cv_deadzone[arg]); + M_SetItemCvar(MN_OP_CHANGECONTROLS, "XDEADZ", &cv_deadzonex[arg]); + M_SetItemCvar(MN_OP_CHANGECONTROLS, "YDEADZ", &cv_deadzoney[arg]); + M_SetItemCvar(MN_OP_CHANGECONTROLS, "TDEADZ", &cv_deadzonet[arg]); M_SetItemCvar(MN_OP_CHANGECONTROLS, "DEAZS", &cv_deadzonestyle[arg]); M_SetItemCvar(MN_OP_CHANGECONTROLS, "TURNSMOOTHING", &cv_turnsmooth[arg]); M_SetItemCvar(MN_OP_CHANGECONTROLS, "LITESTEER", &cv_litesteer[arg]); diff --git a/src/p_tick.c b/src/p_tick.c index e3aa7046f..310be705b 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -944,7 +944,7 @@ void P_Ticker(boolean run) G_WriteAllGhostTics(); if (cv_recordmultiplayerdemos.value && (demo.savemode == DSM_NOTSAVING || demo.savemode == DSM_WILLAUTOSAVE)) - if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && G_PlayerInputDown(0, gc_lookback, false)) + if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && G_PlayerInputDown(0, gc_lookback, false, DEADZONE_BUTTON)) demo.savemode = DSM_TITLEENTRY; } else if (demo.playback) // Use Ghost data for consistency checks. diff --git a/src/y_inter.c b/src/y_inter.c index c44bf016a..458650138 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -747,7 +747,7 @@ void Y_Ticker(void) if (demo.recording) { - if (demo.savemode == DSM_NOTSAVING && G_PlayerInputDown(0, gc_lookback, false)) + if (demo.savemode == DSM_NOTSAVING && G_PlayerInputDown(0, gc_lookback, false, DEADZONE_BUTTON)) demo.savemode = DSM_TITLEENTRY; if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE) @@ -1818,13 +1818,13 @@ void Y_VoteTicker(void) && !voteclient.playerinfo[i].delay && g_pickedVote == VOTE_NOT_PICKED && g_votes[p] == VOTE_NOT_PICKED) { - if (G_PlayerInputDown(i, gc_aimforward, false)) + if (G_PlayerInputDown(i, gc_aimforward, false, DEADZONE_Y)) { voteclient.playerinfo[i].selection--; pressed = true; } - if (G_PlayerInputDown(i, gc_aimbackward, false) && pressed == false) + if (G_PlayerInputDown(i, gc_aimbackward, false, DEADZONE_Y) && pressed == false) { voteclient.playerinfo[i].selection++; pressed = true; @@ -1833,7 +1833,7 @@ void Y_VoteTicker(void) if (votemax > 1) // only allow side-movements for multi-row selections { // HORRIBLE hack, my GOD - if (G_PlayerInputDown(i, gc_turnright, false) && !pressed) // move right + if (G_PlayerInputDown(i, gc_turnright, false, DEADZONE_X) && !pressed) // move right { if (voteclient.playerinfo[i].selection <= votewrap) voteclient.playerinfo[i].selection += 4; @@ -1842,7 +1842,7 @@ void Y_VoteTicker(void) pressed = true; } - if (G_PlayerInputDown(i, gc_turnleft, false) && !pressed) // move left + if (G_PlayerInputDown(i, gc_turnleft, false, DEADZONE_X) && !pressed) // move left { if (voteclient.playerinfo[i].selection > 3) voteclient.playerinfo[i].selection -= 4; @@ -1857,7 +1857,7 @@ void Y_VoteTicker(void) if (voteclient.playerinfo[i].selection > ((votemax*3)+((votemax > 1) ? (votemax-1) : 0)) ) voteclient.playerinfo[i].selection = 0; - if (G_PlayerInputDown(i, gc_accelerate, false) && pressed == false) + if (G_PlayerInputDown(i, gc_accelerate, false, DEADZONE_BUTTON) && pressed == false) { D_ModifyClientVote(i, voteclient.playerinfo[i].selection); pressed = true;