From 769ce2ef65e066db86721d941a6ea1aeea144d82 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 25 Mar 2023 20:43:11 -0500 Subject: [PATCH 01/13] Add I_GamepadRumble, I_GamepadRumbleTriggers --- src/i_joy.h | 2 ++ src/sdl/i_system.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/i_joy.h b/src/i_joy.h index 925e69bcf..53824d391 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -62,6 +62,8 @@ void I_SetGamepadPlayerIndex(INT32 device_id, INT32 index); void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue); void I_GetGamepadGuid(INT32 device_id, char *out, int out_len); void I_GetGamepadName(INT32 device_id, char *out, int out_len); +void I_GamepadRumble(INT32 device_id, UINT16 low_strength, UINT16 high_strength); +void I_GamepadRumbleTriggers(INT32 device_id, UINT16 left_strength, UINT16 right_strength); #ifdef __cplusplus } // extern "C" diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index b0598a05b..76cafa09a 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -1019,6 +1019,46 @@ void I_GetGamepadName(INT32 device_id, char *out, int out_len) out[out_len - 1] = 0; } +void I_GamepadRumble(INT32 device_id, UINT16 low_strength, UINT16 high_strength) +{ +#if !(SDL_VERSION_ATLEAST(2,0,9)) + (void)device_id; + (void)low_strength; + (void)high_strength; + (void)length_ms; +#else + I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher + + SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1); + if (controller == NULL) + { + return; + } + + SDL_GameControllerRumble(controller, low_strength, high_strength, 0); +#endif +} + +void I_GamepadRumbleTriggers(INT32 device_id, UINT16 left_strength, UINT16 right_strength) +{ +#if !(SDL_VERSION_ATLEAST(2,0,14)) + (void)device_id; + (void)low_strength; + (void)high_strength; + (void)length_ms; +#else + I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher + + SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1); + if (controller == NULL) + { + return; + } + + SDL_GameControllerRumbleTriggers(controller, left_strength, right_strength, 0); +#endif +} + // // I_StartupInput // From 17daf1aeba259ce31a2c3aecfc8f080e8baa7333 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 25 Mar 2023 21:25:15 -0500 Subject: [PATCH 02/13] Add G_ functions to rumble a player's device --- src/g_input.c | 30 ++++++++++++++++++++++++++++++ src/g_input.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/src/g_input.c b/src/g_input.c index c920b4da7..cae54dae9 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -208,6 +208,8 @@ void G_SetDeviceForPlayer(INT32 player, INT32 device) if (device > 0) { I_SetGamepadPlayerIndex(device, -1); + I_GamepadRumble(device, 0, 0); + I_GamepadRumbleTriggers(device, 0, 0); } } } @@ -327,6 +329,34 @@ void G_ResetAllDeviceResponding(void) } } +void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength) +{ + INT32 device_id; + + device_id = G_GetDeviceForPlayer(player); + + if (device_id < 1) + { + return; + } + + I_GamepadRumble(device_id, low_strength, high_strength); +} + +void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 right_strength) +{ + INT32 device_id; + + device_id = G_GetDeviceForPlayer(player); + + if (device_id < 1) + { + return; + } + + I_GamepadRumbleTriggers(device_id, left_strength, right_strength); +} + static boolean AutomaticControllerReassignmentIsAllowed(INT32 device) { boolean device_is_gamepad = device > 0; diff --git a/src/g_input.h b/src/g_input.h index 70a6b4e73..388a33f91 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -159,6 +159,9 @@ void G_SetDeviceForPlayer(INT32 player, INT32 device); void G_SetPlayerGamepadIndicatorToPlayerColor(INT32 player); +void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength); +void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 right_strength); + /// Get the gamekeydown array (NUMINPUTS values) for the given device, or NULL if the device id is invalid. INT32* G_GetDeviceGameKeyDownArray(INT32 device); From f7ca9043a109274a31f3791d3579454c42283677 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 25 Mar 2023 21:25:47 -0500 Subject: [PATCH 03/13] Add offroad gamepad rumble --- src/k_kart.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 561eb28fa..1bde0b841 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12,6 +12,7 @@ #include "doomdef.h" #include "hu_stuff.h" #include "g_game.h" +#include "g_input.h" // for device rumble #include "m_random.h" #include "p_local.h" #include "p_slopes.h" @@ -8336,6 +8337,31 @@ void K_KartPlayerAfterThink(player_t *player) player->nullHitlag = 0; } + + // Apply rumble to player if local to machine and not in demo playback + if (!demo.playback) + { + int i; + + for (i = 0; i <= splitscreen; i++) + { + if (player == &players[g_localplayers[i]]) + { + UINT16 low = 0; + UINT16 high = 0; + + if (player->offroad > 0 && (player->mo->momx != 0 || player->mo->momy != 0 || player->mo->momz != 0)) + { + low = 65536 / 4; + high = 65536 / 4; + } + + G_PlayerDeviceRumble(i, low, high); + + break; + } + } + } } /*-------------------------------------------------- From 839f2a6d159d1672483a19e998b4d26455c14bc7 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 25 Mar 2023 22:36:34 -0500 Subject: [PATCH 04/13] Add G_ResetAllDeviceRumbles --- src/g_input.c | 16 ++++++++++++++++ src/g_input.h | 1 + 2 files changed, 17 insertions(+) diff --git a/src/g_input.c b/src/g_input.c index cae54dae9..4110df993 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -357,6 +357,22 @@ void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 rig I_GamepadRumbleTriggers(device_id, left_strength, right_strength); } +void G_ResetAllDeviceRumbles(void) +{ + int i; + int devices; + + devices = G_GetNumAvailableGamepads(); + + for (i = 0; i < devices; i++) + { + INT32 device_id = G_GetAvailableGamepadDevice(i); + + I_GamepadRumble(device_id, 0, 0); + I_GamepadRumbleTriggers(device_id, 0, 0); + } +} + static boolean AutomaticControllerReassignmentIsAllowed(INT32 device) { boolean device_is_gamepad = device > 0; diff --git a/src/g_input.h b/src/g_input.h index 388a33f91..6dd262761 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -161,6 +161,7 @@ void G_SetPlayerGamepadIndicatorToPlayerColor(INT32 player); void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength); void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 right_strength); +void G_ResetAllDeviceRumbles(void); /// Get the gamekeydown array (NUMINPUTS values) for the given device, or NULL if the device id is invalid. INT32* G_GetDeviceGameKeyDownArray(INT32 device); From a71c7dfad667f8afc6e314546abf427d67a15f56 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Sat, 25 Mar 2023 22:36:56 -0500 Subject: [PATCH 05/13] Reset device rumble on exitlevel, exitgame, map --- src/d_clisrv.c | 2 ++ src/g_game.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7fef26168..d039af3a6 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2898,6 +2898,8 @@ void CL_Reset(void) http_source[0] = '\0'; #endif + G_ResetAllDeviceRumbles(); + // D_StartTitle should get done now, but the calling function will handle it } diff --git a/src/g_game.c b/src/g_game.c index b96e49283..e68d3585d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1571,6 +1571,8 @@ void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate) { Automate_Run(AEV_ROUNDSTART); } + + G_ResetAllDeviceRumbles(); } void G_DoLoadLevel(boolean resetplayer) @@ -3197,6 +3199,8 @@ void G_AddPlayer(INT32 playernum) void G_ExitLevel(void) { + G_ResetAllDeviceRumbles(); + if (gamestate == GS_LEVEL) { UINT8 i; From c64bdca66720419802c1f3541541e1723a391c4c Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 27 Mar 2023 17:31:07 -0500 Subject: [PATCH 06/13] Reset rumble on net pause and pause menu --- src/d_netcmd.c | 1 + src/menus/transient/pause-game.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index ef313f783..2974ed763 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3315,6 +3315,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) } I_UpdateMouseGrab(); + G_ResetAllDeviceRumbles(); } // Command for stuck characters in netgames, griefing, etc. diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c index f6ad377e0..dcfcfc9f5 100644 --- a/src/menus/transient/pause-game.c +++ b/src/menus/transient/pause-game.c @@ -188,6 +188,8 @@ void M_OpenPauseMenu(void) PAUSE_Main[mpause_entergame].status = IT_STRING | IT_CALL; } } + + G_ResetAllDeviceRumbles(); } void M_QuitPauseMenu(INT32 choice) From 3cd232601e87e0f9fcbb460491548d461ce8c2ec Mon Sep 17 00:00:00 2001 From: Eidolon Date: Wed, 29 Mar 2023 18:07:06 -0500 Subject: [PATCH 07/13] Use boostpower instead of offroad for rumble --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 1bde0b841..c920e836f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8350,7 +8350,7 @@ void K_KartPlayerAfterThink(player_t *player) UINT16 low = 0; UINT16 high = 0; - if (player->offroad > 0 && (player->mo->momx != 0 || player->mo->momy != 0 || player->mo->momz != 0)) + if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) { low = 65536 / 4; high = 65536 / 4; From 7a9779d242142cc4c08cc57f03c98311d655a0fa Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 2 Apr 2023 23:09:56 +0100 Subject: [PATCH 08/13] Remove a bunch of mouse console variables that hold no relevance to us --- src/d_netcmd.c | 4 ---- src/g_game.c | 2 -- src/g_game.h | 9 --------- src/g_input.c | 9 --------- src/g_input.h | 2 -- 5 files changed, 26 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2974ed763..1c99d00cd 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1035,10 +1035,6 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_controlperkey); CV_RegisterVar(&cv_usemouse); - CV_RegisterVar(&cv_invertmouse); - CV_RegisterVar(&cv_mousesens); - CV_RegisterVar(&cv_mouseysens); - //CV_RegisterVar(&cv_mousemove); for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { diff --git a/src/g_game.c b/src/g_game.c index e68d3585d..64d36527a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -416,8 +416,6 @@ consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, C // Display song credits consvar_t cv_songcredits = CVAR_INIT ("songcredits", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL); - consvar_t cv_invincmusicfade = CVAR_INIT ("invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_growmusicfade = CVAR_INIT ("growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL); diff --git a/src/g_game.h b/src/g_game.h index 2ef74e230..41a22a6c5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -70,18 +70,9 @@ extern consvar_t cv_songcredits; extern consvar_t cv_pauseifunfocused; -extern consvar_t cv_invertmouse; - extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_aimaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_lookaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_fireaxis[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_driftaxis[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; diff --git a/src/g_input.c b/src/g_input.c index 4110df993..ac6724087 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -23,16 +23,7 @@ #include "v_video.h" // V_GetColor for assigning gamepad indictaor colors #include "z_zone.h" -#define MAXMOUSESENSITIVITY 100 // sensitivity steps - -static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY, "MAX"}, {0, NULL}}; static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}}; - -// mouse values are used once -consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL); -consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL); -consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL); -consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL); consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL); // current state of the keys diff --git a/src/g_input.h b/src/g_input.h index 6dd262761..64f55653b 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -100,8 +100,6 @@ typedef enum } gamecontrols_e; // mouse values are used once -extern consvar_t cv_mousesens, cv_mouseysens; -extern consvar_t cv_mousesens2, cv_mouseysens2; extern consvar_t cv_controlperkey; // current state of the keys: JOYAXISRANGE or 0 when boolean. From 89fc9a618e2baea3205f6a0fea704d59927407c3 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 2 Apr 2023 23:16:58 +0100 Subject: [PATCH 09/13] Rumble toggle attached to profile - Will silently merge conflict with !1093, make sure to adjust PROFILEVER handling - (profile_t *)->rumble - cv_rumble[MAXSPLITSCREENPLAYERS] - cv_dummyprofilerumble - Disables all current rumbles when toggling off - Prevents new rumbles from being set while turned off --- src/d_netcmd.c | 1 + src/g_game.c | 36 ++++++++++++++++++++++ src/g_input.c | 25 +++++++++++++++ src/g_input.h | 3 ++ src/k_menu.h | 1 + src/k_menufunc.c | 1 + src/k_profiles.c | 10 ++++++ src/k_profiles.h | 3 +- src/menus/options-profiles-1.c | 3 ++ src/menus/options-profiles-edit-controls.c | 6 ++++ 10 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 1c99d00cd..a7060a31d 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1024,6 +1024,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_kickstartaccel[i]); CV_RegisterVar(&cv_shrinkme[i]); CV_RegisterVar(&cv_deadzone[i]); + CV_RegisterVar(&cv_rumble[i]); } // filesrch.c diff --git a/src/g_game.c b/src/g_game.c index 64d36527a..0adcbe98f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -353,6 +353,11 @@ static void weaponPrefChange2(void); static void weaponPrefChange3(void); static void weaponPrefChange4(void); +static void rumble_off_handle(void); +static void rumble_off_handle2(void); +static void rumble_off_handle3(void); +static void rumble_off_handle4(void); + // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. // chat timer thingy @@ -445,6 +450,13 @@ consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("deadzone4", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) }; +consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle), + CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle2), + CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle3), + CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle4) +}; + // now automatically allocated in D_RegisterClientCommands // so that it doesn't have to be updated depending on the value of MAXPLAYERS char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; @@ -1474,6 +1486,30 @@ static void weaponPrefChange4(void) WeaponPref_Send(3); } +static void rumble_off_handle(void) +{ + if (cv_rumble[0].value == 0) + G_ResetPlayerDeviceRumble(0); +} + +static void rumble_off_handle2(void) +{ + if (cv_rumble[1].value == 0) + G_ResetPlayerDeviceRumble(1); +} + +static void rumble_off_handle3(void) +{ + if (cv_rumble[2].value == 0) + G_ResetPlayerDeviceRumble(2); +} + +static void rumble_off_handle4(void) +{ + if (cv_rumble[3].value == 0) + G_ResetPlayerDeviceRumble(3); +} + // // G_DoLoadLevelEx // diff --git a/src/g_input.c b/src/g_input.c index ac6724087..5883cc36d 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -324,6 +324,11 @@ void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strengt { INT32 device_id; + if (cv_rumble[player].value == 0) + { + return; + } + device_id = G_GetDeviceForPlayer(player); if (device_id < 1) @@ -338,6 +343,11 @@ void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 rig { INT32 device_id; + if (cv_rumble[player].value == 0) + { + return; + } + device_id = G_GetDeviceForPlayer(player); if (device_id < 1) @@ -348,6 +358,21 @@ void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 rig I_GamepadRumbleTriggers(device_id, left_strength, right_strength); } +void G_ResetPlayerDeviceRumble(INT32 player) +{ + INT32 device_id; + + device_id = G_GetDeviceForPlayer(player); + + if (device_id < 1) + { + return; + } + + I_GamepadRumble(device_id, 0, 0); + I_GamepadRumbleTriggers(device_id, 0, 0); +} + void G_ResetAllDeviceRumbles(void) { int i; diff --git a/src/g_input.h b/src/g_input.h index 64f55653b..bd52d6ca4 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -157,8 +157,11 @@ void G_SetDeviceForPlayer(INT32 player, INT32 device); void G_SetPlayerGamepadIndicatorToPlayerColor(INT32 player); +extern consvar_t cv_rumble[MAXSPLITSCREENPLAYERS]; + void G_PlayerDeviceRumble(INT32 player, UINT16 low_strength, UINT16 high_strength); void G_PlayerDeviceRumbleTriggers(INT32 player, UINT16 left_strength, UINT16 right_strength); +void G_ResetPlayerDeviceRumble(INT32 player); void G_ResetAllDeviceRumbles(void); /// Get the gamekeydown array (NUMINPUTS values) for the given device, or NULL if the device id is invalid. diff --git a/src/k_menu.h b/src/k_menu.h index cd7bbbe68..e1e4af6ce 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -945,6 +945,7 @@ extern INT16 controlleroffsets[][2]; extern consvar_t cv_dummyprofilename; extern consvar_t cv_dummyprofileplayername; extern consvar_t cv_dummyprofilekickstart; +extern consvar_t cv_dummyprofilerumble; void M_ResetOptions(void); void M_InitOptions(INT32 choice); // necessary for multiplayer since there's some options we won't want to access diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 4727f2fbe..fc16f606d 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -1171,6 +1171,7 @@ void M_Init(void) CV_RegisterVar(&cv_dummyprofilename); CV_RegisterVar(&cv_dummyprofileplayername); CV_RegisterVar(&cv_dummyprofilekickstart); + CV_RegisterVar(&cv_dummyprofilerumble); CV_RegisterVar(&cv_dummygpdifficulty); CV_RegisterVar(&cv_dummykartspeed); diff --git a/src/k_profiles.c b/src/k_profiles.c index aad3fd221..d43253dfa 100644 --- a/src/k_profiles.c +++ b/src/k_profiles.c @@ -88,6 +88,7 @@ profile_t* PR_MakeProfileFromPlayer(const char *prname, const char *pname, const // Player bound cvars: new->kickstartaccel = cv_kickstartaccel[pnum].value; + new->rumble = cv_rumble[pnum].value; return new; } @@ -277,6 +278,7 @@ void PR_SaveProfiles(void) // Consvars. WRITEUINT8(save.p, profilesList[i]->kickstartaccel); + WRITEUINT8(save.p, profilesList[i]->rumble); // Controls. for (j = 0; j < num_gamecontrols; j++) @@ -409,6 +411,14 @@ void PR_LoadProfiles(void) // Consvars. profilesList[i]->kickstartaccel = (boolean)READUINT8(save.p); + if (version < 4) + { + profilesList[i]->rumble = true; + } + else + { + profilesList[i]->rumble = (boolean)READUINT8(save.p); + } // Controls. for (j = 0; j < num_gamecontrols; j++) diff --git a/src/k_profiles.h b/src/k_profiles.h index c5e49bab9..06b880c42 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -31,7 +31,7 @@ extern "C" { #define SKINNAMESIZE 16 #define PROFILENAMELEN 6 -#define PROFILEVER 3 +#define PROFILEVER 4 #define MAXPROFILES 16 #define PROFILESFILE "ringprofiles.prf" #define PROFILE_GUEST 0 @@ -74,6 +74,7 @@ struct profile_t // Player-specific consvars. // @TODO: List all of those boolean kickstartaccel; // cv_kickstartaccel + boolean rumble; // cv_rumble // Finally, control data itself INT32 controls[num_gamecontrols][MAXINPUTMAPPING]; // Lists of all the controls, defined the same way as default inputs in g_input.c diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index 17d4c241b..311788bb1 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -30,6 +30,7 @@ menu_t OPTIONS_ProfilesDef = { consvar_t cv_dummyprofilename = CVAR_INIT ("dummyprofilename", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummyprofileplayername = CVAR_INIT ("dummyprofileplayername", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummyprofilekickstart = CVAR_INIT ("dummyprofilekickstart", "Off", CV_HIDDEN, CV_OnOff, NULL); +consvar_t cv_dummyprofilerumble = CVAR_INIT ("dummyprofilerumble", "On", CV_HIDDEN, CV_OnOff, NULL); void M_ProfileSelectInit(INT32 choice) { @@ -92,12 +93,14 @@ static void M_StartEditProfile(INT32 c) CV_StealthSet(&cv_dummyprofilename, optionsmenu.profile->profilename); CV_StealthSet(&cv_dummyprofileplayername, optionsmenu.profile->playername); CV_StealthSetValue(&cv_dummyprofilekickstart, optionsmenu.profile->kickstartaccel); + CV_StealthSetValue(&cv_dummyprofilerumble, optionsmenu.profile->rumble); } else { CV_StealthSet(&cv_dummyprofilename, ""); CV_StealthSet(&cv_dummyprofileplayername, ""); CV_StealthSetValue(&cv_dummyprofilekickstart, 0); // off + CV_StealthSetValue(&cv_dummyprofilerumble, 1); // on } // Setup greyout and stuff. diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 779fc625c..f3dd23871 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -83,6 +83,9 @@ menuitem_t OPTIONS_ProfileControls[] = { {IT_HEADER, "TOGGLES", "For per-player commands", NULL, {NULL}, 0, 0}, + {IT_CONTROL | IT_CVAR, "RUMBLE", "For gamepad users - should your device rumble?", + NULL, {.cvar = &cv_dummyprofilerumble}, 0, 0}, + {IT_CONTROL | IT_CVAR, "KICKSTART ACCEL", "Hold A to auto-accel. Tap it to cancel.", NULL, {.cvar = &cv_dummyprofilekickstart}, 0, 0}, @@ -182,6 +185,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) SINT8 belongsto = PR_ProfileUsedBy(optionsmenu.profile); // Save the profile optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; + optionsmenu.profile->rumble = cv_dummyprofilerumble.value; memcpy(&optionsmenu.profile->controls, optionsmenu.tempcontrols, sizeof(gamecontroldefault)); // If this profile is in-use by anyone, apply the changes immediately upon exiting. @@ -190,6 +194,7 @@ static void M_ProfileControlSaveResponse(INT32 choice) { memcpy(&gamecontrol[belongsto], optionsmenu.tempcontrols, sizeof(gamecontroldefault)); CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value); + CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value); } M_GoBack(0); @@ -206,6 +211,7 @@ void M_ProfileControlsConfirm(INT32 choice) M_ProfileControlSaveResponse(MA_YES); optionsmenu.profile->kickstartaccel = cv_dummyprofilekickstart.value; // Make sure to save kickstart accel. + optionsmenu.profile->rumble = cv_dummyprofilerumble.value; // And rumble too! // Reapply player 1's real profile. if (cv_currprofile.value > -1) From 380beaa0233f81c401ee5e9895fc54932561a94f Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 2 Apr 2023 23:49:45 +0100 Subject: [PATCH 10/13] Refactor Rumble condition check to iterate over splitscreen players once in p_tick.c, instead of players*splitscreen players in k_kart.c --- src/k_kart.c | 25 ------------------------- src/p_tick.c | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c920e836f..a0730608c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8337,31 +8337,6 @@ void K_KartPlayerAfterThink(player_t *player) player->nullHitlag = 0; } - - // Apply rumble to player if local to machine and not in demo playback - if (!demo.playback) - { - int i; - - for (i = 0; i <= splitscreen; i++) - { - if (player == &players[g_localplayers[i]]) - { - UINT16 low = 0; - UINT16 high = 0; - - if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) - { - low = 65536 / 4; - high = 65536 / 4; - } - - G_PlayerDeviceRumble(i, low, high); - - break; - } - } - } } /*-------------------------------------------------- diff --git a/src/p_tick.c b/src/p_tick.c index 7327e5c1d..4c731bf9d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -747,6 +747,28 @@ void P_Ticker(boolean run) } } + // Apply rumble to player if local to machine and not in demo playback + if (!demo.playback) + { + for (i = 0; i <= splitscreen; i++) + { + player_t *player = &players[g_localplayers[i]]; + UINT16 low = 0; + UINT16 high = 0; + + if (player->mo == NULL) + continue; + + if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) + { + low = 65536 / 4; + high = 65536 / 4; + } + + G_PlayerDeviceRumble(i, low, high); + } + } + if (numFinishingPlayers > 1) { for (i = 0; i < numFinishingPlayers; i++) From 6942298862616bff09ff17167597c9713f775cbc Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 2 Apr 2023 23:55:16 +0100 Subject: [PATCH 11/13] Adjustments to Rumble - Cause more intense rumble for damage/damage-causing hitlag - Reduce intensity for offroad/bananadrag rumble --- src/p_tick.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_tick.c b/src/p_tick.c index 4c731bf9d..46be683f0 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -759,10 +759,15 @@ void P_Ticker(boolean run) if (player->mo == NULL) continue; - if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) + if ((player->mo->eflags & MFE_DAMAGEHITLAG) && player->mo->hitlag) { - low = 65536 / 4; - high = 65536 / 4; + low = 65536 / 2; + high = 65536 / 2; + } + else if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) + { + low = 65536 / 32; + high = 65536 / 32; } G_PlayerDeviceRumble(i, low, high); From 8c58cde072a426ec37fc89dd200bb4e2828a7619 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 3 Apr 2023 00:13:17 +0100 Subject: [PATCH 12/13] Rumble: Also vibrate on the first half-second of a sneaker (panel), attenuating in strength with numsneakers. --- src/p_tick.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_tick.c b/src/p_tick.c index 46be683f0..be1efb337 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -764,6 +764,11 @@ void P_Ticker(boolean run) low = 65536 / 2; high = 65536 / 2; } + else if (player->sneakertimer > (sneakertime-(TICRATE/2))) + { + low = 65536 / (3+player->numsneakers); + high = 65536 / (3+player->numsneakers); + } else if (player->boostpower < FRACUNIT && P_IsObjectOnGround(player->mo)) { low = 65536 / 32; From 6e819e15068373438a6d7c54fccac596f20ec988 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 3 Apr 2023 10:37:03 +0100 Subject: [PATCH 13/13] rumble2 rumble3 rumble4 typo --- src/g_game.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 0adcbe98f..ab41a7139 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -452,9 +452,9 @@ consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS] = { consvar_t cv_rumble[MAXSPLITSCREENPLAYERS] = { CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle), - CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle2), - CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle3), - CVAR_INIT ("rumble", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle4) + CVAR_INIT ("rumble2", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle2), + CVAR_INIT ("rumble3", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle3), + CVAR_INIT ("rumble4", "On", CV_SAVE|CV_CALL, CV_OnOff, rumble_off_handle4) }; // now automatically allocated in D_RegisterClientCommands