diff --git a/src/command.c b/src/command.c index d1db9f9c9..201cceeee 100644 --- a/src/command.c +++ b/src/command.c @@ -2181,6 +2181,132 @@ static void CV_EnforceExecVersion(void) CV_StealthSetValue(&cv_execversion, EXECVERSION); } +static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr) +{ + // If ALL axis settings are previous defaults, set them to the new defaults + // EXECVERSION < 26 (2.1.21) + + if (joyaxis_default) + { + if (!stricmp(v->name, "joyaxis_turn")) + { + if (joyaxis_count > 6) return false; + // we're currently setting the new defaults, don't interfere + else if (joyaxis_count == 6) return true; + + if (!stricmp(valstr, "X-Axis")) joyaxis_count++; + else joyaxis_default = false; + } + if (!stricmp(v->name, "joyaxis_move")) + { + if (joyaxis_count > 6) return false; + else if (joyaxis_count == 6) return true; + + if (!stricmp(valstr, "Y-Axis")) joyaxis_count++; + else joyaxis_default = false; + } + if (!stricmp(v->name, "joyaxis_side")) + { + if (joyaxis_count > 6) return false; + else if (joyaxis_count == 6) return true; + + if (!stricmp(valstr, "Z-Axis")) joyaxis_count++; + else joyaxis_default = false; + } + if (!stricmp(v->name, "joyaxis_look")) + { + if (joyaxis_count > 6) return false; + else if (joyaxis_count == 6) return true; + + if (!stricmp(valstr, "None")) joyaxis_count++; + else joyaxis_default = false; + } + if (!stricmp(v->name, "joyaxis_fire") + || !stricmp(v->name, "joyaxis_firenormal")) + { + if (joyaxis_count > 6) return false; + else if (joyaxis_count == 6) return true; + + if (!stricmp(valstr, "None")) joyaxis_count++; + else joyaxis_default = false; + } + // reset all axis settings to defaults + if (joyaxis_count == 6) + { + COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis[0].name, cv_turnaxis[0].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis[0].name, cv_moveaxis[0].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis[0].name, cv_sideaxis[0].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis[0].name, cv_lookaxis[0].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis[0].name, cv_fireaxis[0].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis[0].name, cv_firenaxis[0].defaultvalue)); + joyaxis_count++; + return false; + } + } + + if (joyaxis2_default) + { + if (!stricmp(v->name, "joyaxis2_turn")) + { + if (joyaxis2_count > 6) return false; + // we're currently setting the new defaults, don't interfere + else if (joyaxis2_count == 6) return true; + + if (!stricmp(valstr, "X-Axis")) joyaxis2_count++; + else joyaxis2_default = false; + } + if (!stricmp(v->name, "joyaxis2_move")) + { + if (joyaxis2_count > 6) return false; + else if (joyaxis2_count == 6) return true; + + if (!stricmp(valstr, "Y-Axis")) joyaxis2_count++; + else joyaxis2_default = false; + } + if (!stricmp(v->name, "joyaxis2_side")) + { + if (joyaxis2_count > 6) return false; + else if (joyaxis2_count == 6) return true; + + if (!stricmp(valstr, "Z-Axis")) joyaxis2_count++; + else joyaxis2_default = false; + } + if (!stricmp(v->name, "joyaxis2_look")) + { + if (joyaxis2_count > 6) return false; + else if (joyaxis2_count == 6) return true; + + if (!stricmp(valstr, "None")) joyaxis2_count++; + else joyaxis2_default = false; + } + if (!stricmp(v->name, "joyaxis2_fire") + || !stricmp(v->name, "joyaxis2_firenormal")) + { + if (joyaxis2_count > 6) return false; + else if (joyaxis2_count == 6) return true; + + if (!stricmp(valstr, "None")) joyaxis2_count++; + else joyaxis2_default = false; + } + + // reset all axis settings to defaults + if (joyaxis2_count == 6) + { + COM_BufInsertText(va("%s \"%s\"\n", cv_turnaxis[1].name, cv_turnaxis[1].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_moveaxis[1].name, cv_moveaxis[1].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_sideaxis[1].name, cv_sideaxis[1].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_lookaxis[1].name, cv_lookaxis[1].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_fireaxis[1].name, cv_fireaxis[1].defaultvalue)); + COM_BufInsertText(va("%s \"%s\"\n", cv_firenaxis[1].name, cv_firenaxis[1].defaultvalue)); + joyaxis2_count++; + return false; + } + } + + // we haven't reached our counts yet, or we're not default + return true; +} + #ifndef OLD_GAMEPAD_AXES static boolean CV_ConvertOldJoyAxisVars(consvar_t *v, const char *valstr) { @@ -2233,6 +2359,40 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr) if (!(v->flags & CV_SAVE)) return true; + if (GETMAJOREXECVERSION(cv_execversion.value) < 26) // 26 = 2.1.21 + { + // MOUSE SETTINGS + // alwaysfreelook split between first and third person (chasefreelook) + // mousemove was on by default, which invalidates the current approach + if (!stricmp(v->name, "alwaysmlook") + || !stricmp(v->name, "alwaysmlook2") + || !stricmp(v->name, "mousemove") + || !stricmp(v->name, "mousemove2")) + return false; + + // mousesens was changed from 35 to 20 due to oversensitivity + if ((!stricmp(v->name, "mousesens") + || !stricmp(v->name, "mousesens2") + || !stricmp(v->name, "mouseysens") + || !stricmp(v->name, "mouseysens2")) + && atoi(valstr) == 35) + return false; + + // GAMEPAD DEFAULTS + // use_gamepad was changed from 0 to 1 to automatically use a gamepad if available +#if defined(HAVE_SDL) || defined(_WINDOWS) + if ((!stricmp(v->name, "use_joystick") + || !stricmp(v->name, "use_joystick2")) + && atoi(valstr) == 0) + return false; +#endif + + // axis defaults were changed to be friendly to 360 controllers + // if ALL axis settings are defaults, then change them to new values + if (!CV_FilterJoyAxisVars(v, valstr)) + return false; + } + #ifndef OLD_GAMEPAD_AXES if (GETMAJOREXECVERSION(cv_execversion.value) <= 51 && GETMINOREXECVERSION(cv_execversion.value) < 1) { diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f721aa75a..07dba1777 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -815,6 +815,14 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_moveaxis[1]); CV_RegisterVar(&cv_lookaxis[0]); CV_RegisterVar(&cv_lookaxis[1]); + CV_RegisterVar(&cv_jumpaxis[0]); + CV_RegisterVar(&cv_jumpaxis[1]); + CV_RegisterVar(&cv_spinaxis[0]); + CV_RegisterVar(&cv_spinaxis[1]); + CV_RegisterVar(&cv_fireaxis[0]); + CV_RegisterVar(&cv_fireaxis[1]); + CV_RegisterVar(&cv_firenaxis[0]); + CV_RegisterVar(&cv_firenaxis[1]); CV_RegisterVar(&cv_deadzone[0]); CV_RegisterVar(&cv_deadzone[1]); CV_RegisterVar(&cv_digitaldeadzone[0]); @@ -834,6 +842,7 @@ void D_RegisterClientCommands(void) #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) CV_RegisterVar(&cv_mouse2opt); #endif + CV_RegisterVar(&cv_controlperkey); CV_RegisterVar(&cv_usemouse); CV_RegisterVar(&cv_usemouse2); diff --git a/src/deh_tables.c b/src/deh_tables.c index 90c3047a8..a2cc9732d 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -5648,6 +5648,11 @@ struct int_const_s const INT_CONST[] = { {"JA_MOVE",JA_MOVE}, {"JA_LOOK",JA_LOOK}, {"JA_STRAFE",JA_STRAFE}, + {"JA_DIGITAL",JA_DIGITAL}, + {"JA_JUMP",JA_JUMP}, + {"JA_SPIN",JA_SPIN}, + {"JA_FIRE",JA_FIRE}, + {"JA_FIRENORMAL",JA_FIRENORMAL}, {"JOYAXISRANGE",OLDJOYAXISRANGE}, // Game controls diff --git a/src/g_game.c b/src/g_game.c index dc12c2bab..b4a127a73 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -297,13 +297,17 @@ CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, #ifndef OLD_GAMEPAD_AXES #define MOVEAXIS_DEFAULT "Left Stick Y" #define SIDEAXIS_DEFAULT "Left Stick X" -#define LOOKAXIS_DEFAULT "Right Stick Y" +#define LOOKAXIS_DEFAULT "Right Stick Y-" #define TURNAXIS_DEFAULT "Right Stick X" +#define FIREAXIS_DEFAULT "Right Trigger" +#define FIRENAXIS_DEFAULT "Left Trigger" #else #define MOVEAXIS_DEFAULT "Y-Axis" #define SIDEAXIS_DEFAULT "X-Axis" #define LOOKAXIS_DEFAULT "Y-Rudder-" #define TURNAXIS_DEFAULT "X-Rudder" +#define FIREAXIS_DEFAULT "Z-Rudder" +#define FIRENAXIS_DEFAULT "Z-Axis" #endif // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. @@ -435,6 +439,22 @@ consvar_t cv_turnaxis[2] = { CVAR_INIT ("joyaxis_turn", TURNAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), CVAR_INIT ("joyaxis2_turn", TURNAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) }; +consvar_t cv_jumpaxis[2] = { + CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL) +}; +consvar_t cv_spinaxis[2] = { + CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL) +}; +consvar_t cv_fireaxis[2] = { + CVAR_INIT ("joyaxis_fire", FIREAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_fire", FIREAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) +}; +consvar_t cv_firenaxis[2] = { + CVAR_INIT ("joyaxis_firenormal", FIRENAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_firenormal", FIRENAXIS_DEFAULT, CV_SAVE, joyaxis_cons_t, NULL) +}; consvar_t cv_deadzone[2] = { CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) @@ -870,7 +890,7 @@ static gamepad_axis_e ConvertXboxControllerAxes(int type) } #endif -static INT16 GetJoystickAxisValue(INT32 axisval) +static INT16 GetJoystickAxisValue(UINT8 which, joyaxis_e axissel, INT32 axisval) { boolean flp = false; @@ -905,7 +925,14 @@ static INT16 GetJoystickAxisValue(INT32 axisval) } INT16 retaxis = G_GetGamepadAxisValue(0, gp_axis); - + + if (gamepads[which].digital && axissel >= JA_DIGITAL) + { + const UINT16 jdeadzone = G_GetGamepadDigitalDeadZone(which) / 2; + if (-jdeadzone < retaxis && retaxis < jdeadzone) + return 0; + } + // flip it around if (flp) { @@ -938,11 +965,23 @@ INT16 G_JoyAxis(UINT8 which, joyaxis_e axissel) case JA_STRAFE: axisval = cv_sideaxis[which].value; break; + case JA_JUMP: + axisval = cv_jumpaxis[which].value; + break; + case JA_SPIN: + axisval = cv_spinaxis[which].value; + break; + case JA_FIRE: + axisval = cv_fireaxis[which].value; + break; + case JA_FIRENORMAL: + axisval = cv_firenaxis[which].value; + break; default: return 0; } - value = GetJoystickAxisValue(axisval); + value = GetJoystickAxisValue(which, axissel, axisval); if (axissel == JA_LOOK) { // Look is inverted because +Y goes _down_ in gamepads. @@ -1053,7 +1092,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) boolean forcestrafe = false; boolean forcefullinput = false; - INT32 tspeed, forward, side, strafeaxis, moveaxis, turnaxis, lookaxis, i; + INT32 tspeed, forward, side, axis, strafeaxis, moveaxis, turnaxis, lookaxis, i; joystickvector2_t movejoystickvector, lookjoystickvector; @@ -1339,11 +1378,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } // fire with any button/key - if (G_PlayerInputDown(forplayer, GC_FIRE)) + axis = G_JoyAxis(forplayer, JA_FIRE); + if (G_PlayerInputDown(forplayer, GC_FIRE) || (usegamepad && axis > 0)) cmd->buttons |= BT_ATTACK; // fire normal with any button/key - if (G_PlayerInputDown(forplayer, GC_FIRENORMAL)) + axis = G_JoyAxis(forplayer, JA_FIRENORMAL); + if (G_PlayerInputDown(forplayer, GC_FIRENORMAL) || (usegamepad && axis > 0)) cmd->buttons |= BT_FIRENORMAL; if (G_PlayerInputDown(forplayer, GC_TOSSFLAG)) @@ -1358,7 +1399,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->buttons |= BT_CUSTOM3; // spin with any button/key - if (G_PlayerInputDown(forplayer, GC_SPIN)) + axis = G_JoyAxis(forplayer, JA_SPIN); + if (G_PlayerInputDown(forplayer, GC_SPIN) || (usegamepad && axis > 0)) cmd->buttons |= BT_SPIN; // Centerview can be a toggle in simple mode! @@ -1474,7 +1516,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) resetdown[forplayer] = false; // jump button - if (G_PlayerInputDown(forplayer, GC_JUMP)) + axis = G_JoyAxis(forplayer, JA_JUMP); + if (G_PlayerInputDown(forplayer, GC_JUMP) || (usegamepad && axis > 0)) cmd->buttons |= BT_JUMP; // player aiming shit, ahhhh... diff --git a/src/g_game.h b/src/g_game.h index 8d6e84b12..e798176af 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -71,6 +71,7 @@ extern consvar_t cv_autobrake, cv_autobrake2; extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest; extern consvar_t cv_sideaxis[2], cv_turnaxis[2], cv_moveaxis[2], cv_lookaxis[2], + cv_jumpaxis[2], cv_spinaxis[2], cv_fireaxis[2], cv_firenaxis[2], cv_deadzone[2], cv_digitaldeadzone[2]; extern CV_PossibleValue_t joyaxis_cons_t[]; @@ -97,6 +98,13 @@ typedef enum JA_MOVE, JA_LOOK, JA_STRAFE, + + JA_DIGITAL, // axes henceforth use digital deadzone + + JA_JUMP = JA_DIGITAL, + JA_SPIN, + JA_FIRE, + JA_FIRENORMAL, } joyaxis_e; INT16 G_JoyAxis(UINT8 which, joyaxis_e axissel); diff --git a/src/g_input.c b/src/g_input.c index 87f4d5173..6b0da7e41 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -24,12 +24,14 @@ #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); mouse_t mouse; mouse_t mouse2; @@ -960,6 +962,9 @@ static keyname_t keynames[] = DEF_GAMEPAD_AXIS(TRIGGERLEFT, "left trigger"), DEF_GAMEPAD_AXIS(TRIGGERRIGHT, "right trigger"), +#undef DEF_GAMEPAD_NAME +#undef DEF_GAMEPAD_AXIS + {KEY_DBLMOUSE1+0, "dblmouse1"}, {KEY_DBLMOUSE1+1, "dblmouse2"}, {KEY_DBLMOUSE1+2, "dblmouse3"}, @@ -978,50 +983,7 @@ static keyname_t keynames[] = {KEY_DBL2MOUSE1+7, "dblsec_mouse8"} }; -static keyname_t oldjoynames[] = -{ - DEF_GAMEPAD_NAME(A, "joy1"), - DEF_GAMEPAD_NAME(B, "joy2"), - DEF_GAMEPAD_NAME(X, "joy3"), - DEF_GAMEPAD_NAME(Y, "joy4"), - - DEF_GAMEPAD_NAME(BACK, "joy7"), - DEF_GAMEPAD_NAME(START, "joy8"), - DEF_GAMEPAD_NAME(LEFTSTICK, "joy9"), - DEF_GAMEPAD_NAME(RIGHTSTICK, "joy10"), - - DEF_GAMEPAD_NAME(LEFTSHOULDER, "joy5"), - DEF_GAMEPAD_NAME(RIGHTSHOULDER, "joy6"), - - DEF_GAMEPAD_NAME(DPAD_UP, "hatup"), - DEF_GAMEPAD_NAME(DPAD_DOWN, "hatdown"), - DEF_GAMEPAD_NAME(DPAD_LEFT, "hatleft"), - DEF_GAMEPAD_NAME(DPAD_RIGHT, "hatright"), - - DEF_GAMEPAD_NAME(A, "sec_joy1"), - DEF_GAMEPAD_NAME(B, "sec_joy2"), - DEF_GAMEPAD_NAME(X, "sec_joy3"), - DEF_GAMEPAD_NAME(Y, "sec_joy4"), - - DEF_GAMEPAD_NAME(BACK, "sec_joy7"), - DEF_GAMEPAD_NAME(START, "sec_joy8"), - DEF_GAMEPAD_NAME(LEFTSTICK, "sec_joy9"), - DEF_GAMEPAD_NAME(RIGHTSTICK, "sec_joy10"), - - DEF_GAMEPAD_NAME(LEFTSHOULDER, "sec_joy5"), - DEF_GAMEPAD_NAME(RIGHTSHOULDER, "sec_joy6"), - - DEF_GAMEPAD_NAME(DPAD_UP, "sec_hatup"), - DEF_GAMEPAD_NAME(DPAD_DOWN, "sec_hatdown"), - DEF_GAMEPAD_NAME(DPAD_LEFT, "sec_hatleft"), - DEF_GAMEPAD_NAME(DPAD_RIGHT, "sec_hatright"), -}; - -#undef DEF_GAMEPAD_NAME -#undef DEF_GAMEPAD_AXIS - #define NUMKEYNAMES (sizeof(keynames) / sizeof(keyname_t)) -#define NUMOLDJOYNAMES (sizeof(oldjoynames) / sizeof(keyname_t)) static keyname_t displaykeynames[] = { @@ -1310,10 +1272,6 @@ INT32 G_KeyNameToNum(const char *keystr) if (!stricmp(keynames[j].name, keystr)) return keynames[j].keynum; - for (j = 0; j < NUMOLDJOYNAMES; j++) - if (!stricmp(oldjoynames[j].name, keystr)) - return oldjoynames[j].keynum; - return 0; } @@ -1419,17 +1377,15 @@ void G_DefineDefaultControls(void) gamecontroldefault[i][GC_CUSTOM1 ][1] = GAMEPAD_KEY(B); // B gamecontroldefault[i][GC_CUSTOM2 ][1] = GAMEPAD_KEY(Y); // Y gamecontroldefault[i][GC_CUSTOM3 ][1] = GAMEPAD_KEY(LEFTSTICK); // Left Stick - gamecontroldefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // R1 - gamecontroldefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(LEFTSHOULDER); // L1 + gamecontroldefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick + gamecontroldefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(LEFTSHOULDER); // LB + gamecontroldefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // RB gamecontroldefault[i][GC_SCREENSHOT ][1] = GAMEPAD_KEY(BACK); // Back gamecontroldefault[i][GC_SYSTEMMENU ][0] = GAMEPAD_KEY(START); // Start - gamecontroldefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up - gamecontroldefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left - gamecontroldefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right - gamecontroldefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down - gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick - gamecontroldefault[i][GC_FIRE ][1] = GAMEPAD_AXIS(TRIGGERRIGHT); // R2 - gamecontroldefault[i][GC_FIRENORMAL ][1] = GAMEPAD_AXIS(TRIGGERLEFT); // L2 + gamecontroldefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up + gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down + gamecontroldefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left + gamecontroldefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right // Second player only has gamepad defaults gamecontrolbisdefault[i][GC_JUMP ][1] = GAMEPAD_KEY(A); // A @@ -1437,17 +1393,15 @@ void G_DefineDefaultControls(void) gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = GAMEPAD_KEY(B); // B gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = GAMEPAD_KEY(Y); // Y gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = GAMEPAD_KEY(LEFTSTICK); // Left Stick - gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // R1 - gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(LEFTSHOULDER); // L1 + gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick + gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(LEFTSHOULDER); // LB + gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(RIGHTSHOULDER); // RB gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = GAMEPAD_KEY(BACK); // Back //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = GAMEPAD_KEY(START); // Start - gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up - gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left - gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right - //gamecontrolbisdefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down - gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(RIGHTSTICK); // Right Stick - gamecontrolbisdefault[i][GC_FIRE ][1] = GAMEPAD_AXIS(TRIGGERRIGHT); // R2 - gamecontrolbisdefault[i][GC_FIRENORMAL ][1] = GAMEPAD_AXIS(TRIGGERLEFT); // L2 + gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = GAMEPAD_KEY(DPAD_UP); // D-Pad Up + gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = GAMEPAD_KEY(DPAD_DOWN); // D-Pad Down + gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = GAMEPAD_KEY(DPAD_LEFT); // D-Pad Left + //gamecontrolbisdefault[i][GC_SCORES ][1] = GAMEPAD_KEY(DPAD_RIGHT); // D-Pad Right } } @@ -1517,40 +1471,42 @@ void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis } } -INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify, UINT8 player) +INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify) { INT32 result = GC_NULL; - INT32 i; - for (i = 0; i < NUM_GAMECONTROLS; i++) + if (cv_controlperkey.value == 1) { - if (gamecontrol[i][0] == keynum && player != 2) + INT32 i; + for (i = 0; i < NUM_GAMECONTROLS; i++) { - result = i; - if (modify) gamecontrol[i][0] = KEY_NULL; + if (gamecontrol[i][0] == keynum) + { + result = i; + if (modify) gamecontrol[i][0] = KEY_NULL; + } + if (gamecontrol[i][1] == keynum) + { + result = i; + if (modify) gamecontrol[i][1] = KEY_NULL; + } + if (gamecontrolbis[i][0] == keynum) + { + result = i; + if (modify) gamecontrolbis[i][0] = KEY_NULL; + } + if (gamecontrolbis[i][1] == keynum) + { + result = i; + if (modify) gamecontrolbis[i][1] = KEY_NULL; + } + if (result && !modify) + return result; } - if (gamecontrol[i][1] == keynum && player != 2) - { - result = i; - if (modify) gamecontrol[i][1] = KEY_NULL; - } - if (gamecontrolbis[i][0] == keynum && player != 1) - { - result = i; - if (modify) gamecontrolbis[i][0] = KEY_NULL; - } - if (gamecontrolbis[i][1] == keynum && player != 1) - { - result = i; - if (modify) gamecontrolbis[i][1] = KEY_NULL; - } - if (result && !modify) - return result; } - return result; } -static INT32 G_FilterSpecialKeys(INT32 keyidx, INT32 *keynum1, INT32 *keynum2) +static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT32 *keynum1, INT32 *keynum2, boolean *nestedoverride) { // Special case: ignore KEY_PAUSE because it's hardcoded if (keyidx == 0 && *keynum1 == KEY_PAUSE) @@ -1566,6 +1522,99 @@ static INT32 G_FilterSpecialKeys(INT32 keyidx, INT32 *keynum1, INT32 *keynum2) else if (keyidx == 1 && *keynum2 == KEY_PAUSE) return -1; // skip setting control + if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22 + numctrl == GC_WEAPONNEXT || numctrl == GC_WEAPONPREV || numctrl == GC_TOSSFLAG || + numctrl == GC_SPIN || numctrl == GC_CAMRESET || numctrl == GC_JUMP || + numctrl == GC_PAUSE || numctrl == GC_SYSTEMMENU || numctrl == GC_CAMTOGGLE || + numctrl == GC_SCREENSHOT || numctrl == GC_TALKKEY || numctrl == GC_SCORES || + numctrl == GC_CENTERVIEW + )) + { + INT32 keynum = 0, existingctrl = 0; + INT32 defaultkey; + boolean defaultoverride = false; + + // get the default gamecontrol + if (player == 0 && numctrl == GC_SYSTEMMENU) + defaultkey = gamecontrol[numctrl][0]; + else + defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]); + + // Assign joypad button defaults if there is an open slot. + // At this point, gamecontrol/bis should have the default controls + // (unless LOADCONFIG is being run) + // + // If the player runs SETCONTROL in-game, this block should not be reached + // because EXECVERSION is locked onto the latest version. + if (keyidx == 0 && !*keynum1) + { + if (*keynum2) // push keynum2 down; this is an edge case + { + *keynum1 = *keynum2; + *keynum2 = 0; + keynum = *keynum1; + } + else + { + keynum = defaultkey; + defaultoverride = true; + } + } + else if (keyidx == 1 && (!*keynum2 || (!*keynum1 && *keynum2))) // last one is the same edge case as above + { + keynum = defaultkey; + defaultoverride = true; + } + else // default to the specified keynum + keynum = (keyidx == 1 ? *keynum2 : *keynum1); + + // Did our last call override keynum2? + if (*nestedoverride) + { + defaultoverride = true; + *nestedoverride = false; + } + + // Fill keynum2 with the default control + if (keyidx == 0 && !*keynum2) + { + *keynum2 = defaultkey; + // Tell the next call that this is an override + *nestedoverride = true; + + // if keynum2 already matches keynum1, we probably recursed + // so unset it + if (*keynum1 == *keynum2) + { + *keynum2 = 0; + *nestedoverride = false; + } + } + + // check if the key is being used somewhere else before passing it + // pass it through if it's the same numctrl. This is an edge case -- when using + // LOADCONFIG, gamecontrol is not reset with default. + // + // Also, only check if we're actually overriding, to preserve behavior where + // config'd keys overwrite default keys. + if (defaultoverride) + existingctrl = G_CheckDoubleUsage(keynum, false); + + if (keynum && (!existingctrl || existingctrl == numctrl)) + return keynum; + else if (keyidx == 0 && *keynum2) + { + // try it again and push down keynum2 + *keynum1 = *keynum2; + *keynum2 = 0; + return G_FilterKeyByVersion(numctrl, keyidx, player, keynum1, keynum2, nestedoverride); + // recursion *should* be safe because we only assign keynum2 to a joy default + // and then clear it if we find that keynum1 already has the joy default. + } + else + return 0; + } + // All's good, so pass the keynum as-is if (keyidx == 1) return *keynum2; @@ -1579,6 +1628,7 @@ static void setcontrol(INT32 (*gc)[2]) const char *namectrl; INT32 keynum, keynum1, keynum2; INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0); + boolean nestedoverride = false; // Update me for 2.3 namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin"; @@ -1593,20 +1643,20 @@ static void setcontrol(INT32 (*gc)[2]) } keynum1 = G_KeyNameToNum(COM_Argv(2)); keynum2 = G_KeyNameToNum(COM_Argv(3)); - keynum = G_FilterSpecialKeys(0, &keynum1, &keynum2); + keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) { - (void)G_CheckDoubleUsage(keynum, true, player+1); + (void)G_CheckDoubleUsage(keynum, true); // if keynum was rejected, try it again with keynum2 if (!keynum && keynum2) { keynum1 = keynum2; // push down keynum2 keynum2 = 0; - keynum = G_FilterSpecialKeys(0, &keynum1, &keynum2); + keynum = G_FilterKeyByVersion(numctrl, 0, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) - (void)G_CheckDoubleUsage(keynum, true, player+1); + (void)G_CheckDoubleUsage(keynum, true); } } @@ -1615,7 +1665,7 @@ static void setcontrol(INT32 (*gc)[2]) if (keynum2) { - keynum = G_FilterSpecialKeys(1, &keynum1, &keynum2); + keynum = G_FilterKeyByVersion(numctrl, 1, player, &keynum1, &keynum2, &nestedoverride); if (keynum >= 0) { if (keynum != gc[numctrl][0]) diff --git a/src/g_input.h b/src/g_input.h index bb50d3516..fe623034a 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -188,7 +188,6 @@ typedef enum } key_input_e; #define GAMEPAD_KEY(key) (KEY_GAMEPAD + GAMEPAD_BUTTON_##key) -#define GAMEPAD_AXIS(key) (KEY_AXES + GAMEPAD_AXIS_##key) typedef enum { @@ -249,6 +248,7 @@ typedef enum // mouse values are used once extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; +extern consvar_t cv_controlperkey; typedef struct { @@ -354,7 +354,7 @@ void G_DefineDefaultControls(void); INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]); -INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify, UINT8 player); +INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); // sets the members of a mouse_t given position deltas void G_SetMouseDeltas(INT32 dx, INT32 dy, UINT8 ssplayer); diff --git a/src/m_menu.c b/src/m_menu.c index 1e7e1a761..1d5bd65f3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1070,9 +1070,9 @@ static menuitem_t OP_MainMenu[] = { {IT_SUBMENU | IT_STRING, NULL, "Player 1 Controls...", &OP_P1ControlsDef, 10}, {IT_SUBMENU | IT_STRING, NULL, "Player 2 Controls...", &OP_P2ControlsDef, 20}, + {IT_CVAR | IT_STRING, NULL, "Controls per key", &cv_controlperkey, 30}, - {IT_CALL | IT_STRING, NULL, "Video Options...", M_VideoOptions, 40}, - + {IT_CALL | IT_STRING, NULL, "Video Options...", M_VideoOptions, 50}, {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 60}, {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80}, @@ -1080,16 +1080,6 @@ static menuitem_t OP_MainMenu[] = {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 100}, }; -enum -{ - opplayer1, - opplayer2, - opvideo, - opsound, - opserver, - opdata -}; - static menuitem_t OP_P1ControlsMenu[] = { {IT_CALL | IT_STRING, NULL, "Control Configuration...", M_Setup1PControlsMenu, 10}, @@ -1177,11 +1167,15 @@ static menuitem_t OP_Gamepad1Menu[] = {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis[0] , 40}, {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis[0] , 50}, {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis[0] , 60}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis[0] , 70}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis[0] , 80}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis[0] , 90}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis[0] ,100}, - {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 80}, - {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 90}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[0], 100}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[0], 110}, + {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 120}, + {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook, 130}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[0], 140}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[0], 150}, }; static menuitem_t OP_Gamepad2Menu[] = @@ -1191,11 +1185,15 @@ static menuitem_t OP_Gamepad2Menu[] = {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis[1] , 40}, {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis[1] , 50}, {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis[1] , 60}, + {IT_STRING | IT_CVAR, NULL, "Jump Axis" , &cv_jumpaxis[1] , 70}, + {IT_STRING | IT_CVAR, NULL, "Spin Axis" , &cv_spinaxis[1] , 80}, + {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis[1] , 90}, + {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis[1] ,100}, - {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,80}, - {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 90}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[1],100}, - {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[1],110}, + {IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,120}, + {IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Analog Deadzone", &cv_deadzone[1],140}, + {IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER, NULL, "Digital Deadzone", &cv_digitaldeadzone[1],150}, }; static menuitem_t OP_GamepadSetMenu[MAX_CONNECTED_GAMEPADS + 1]; @@ -1543,13 +1541,6 @@ static menuitem_t OP_DataOptionsMenu[] = {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 40}, }; -enum -{ - opdataaddon, - opdatascreenshot, - opdataerase -}; - static menuitem_t OP_ScreenshotOptionsMenu[] = { {IT_HEADER, NULL, "General", NULL, 0}, @@ -3475,7 +3466,7 @@ boolean M_Responder(event_t *ev) if (!useEventHandler) { UINT16 type = currentMenu->menuitems[itemOn].alphaKey; - if (type == MM_YESNO && !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER || ch == KEY_DEL || ch == KEY_BACKSPACE)) + if (type == MM_YESNO && !(ch == ' ' || ch == 'n' || ch == 'y' || ch == KEY_ESCAPE || ch == KEY_ENTER || ch == KEY_DEL)) return true; if (routine) routine(ch); @@ -7046,10 +7037,10 @@ static void M_Options(INT32 choice) (void)choice; // if the player is not admin or server, disable server options - OP_MainMenu[opserver].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); + OP_MainMenu[5].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // if the player is playing _at all_, disable the erase data options - OP_DataOptionsMenu[opdataerase].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); + OP_DataOptionsMenu[2].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainDef.prevMenu = currentMenu; M_SetupNextMenu(&OP_MainDef); @@ -9124,7 +9115,7 @@ static void M_LoadGame(INT32 choice) if (tutorialmap && cv_tutorialprompt.value) { - M_StartMessage("Do you want to \x82play a brief Tutorial\x80?\n\nWe highly recommend this because \nthe controls are slightly different \nfrom other games.\n\nPress the\x82 Y\x80 key or the\x83 A button\x80 to go\nPress the\x82 N\x80 key or the\x83 X button\x80 to skip\n", + M_StartMessage("Do you want to \x82play a brief Tutorial\x80?\n\nWe highly recommend this because \nthe controls are slightly different \nfrom other games.\n\nPress the\x82 Y\x80 key or the\x83 A button\x80 to go\nPress the\x82 N\x80 key or the\x83 Y button\x80 to skip\n", M_FirstTimeResponse, MM_YESNO); return; } @@ -13032,7 +13023,7 @@ static void M_ChangeControlResponse(event_t *ev) setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 } - G_CheckDoubleUsage(ch, true, setupcontrols_secondaryplayer ? 2 : 1); + G_CheckDoubleUsage(ch, true); setupcontrols[control][found] = ch; }