Finalize char select multiplayer

- Add menu control fallbacks.
    - If it could not find a bind using your existing keys, then it looks at default controls.
    - If it could not find it then, and you're P1, then it looks through gamepads, and then lastly settles for keyboard.
    - Changed around the order of operations on the character select menu, to accommodate for this change.
- Added initroutine to menu_t, which is called every time without question when going to a new menu. This solves many, many minor bugs you could experience in the character select menu when changing between menus, due to things only being properly reset when selecting the character select menu option.
This commit is contained in:
Sally Coolatta 2021-12-28 12:02:31 -05:00
parent 0f218b285e
commit 0179466107
9 changed files with 253 additions and 265 deletions

View file

@ -1503,7 +1503,7 @@ static void M_ConfirmConnect(event_t *ev)
#ifndef NONET
if (ev->type == ev_keydown)
{
if (G_PlayerInputDown(0, gc_a, true))
if (G_PlayerInputDown(0, gc_a, 1))
{
if (totalfilesrequestednum > 0)
{
@ -1526,7 +1526,7 @@ static void M_ConfirmConnect(event_t *ev)
M_ClearMenus(true);
}
else if (G_PlayerInputDown(0, gc_b, true))
else if (G_PlayerInputDown(0, gc_b, 1))
{
cl_mode = CL_ABORTED;
M_ClearMenus(true);
@ -1934,7 +1934,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (cl_mode == CL_CONFIRMCONNECT)
D_ProcessEvents(); //needed for menu system to receive inputs
if (G_PlayerInputDown(0, gc_b, true) || cl_mode == CL_ABORTED)
if (G_PlayerInputDown(0, gc_b, 1) || cl_mode == CL_ABORTED)
{
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);

View file

@ -1788,6 +1788,8 @@ static void F_CacheTitleScreen(void)
void F_StartTitleScreen(void)
{
setup_numplayers = 0;
if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)
{
ttuser_count = 0;

View file

@ -652,35 +652,67 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming)
return (INT16)((*aiming)>>16);
}
static INT32 KeyValue(UINT8 p, INT32 key, boolean menu)
static INT32 KeyValue(UINT8 p, INT32 key, UINT8 menuPlayers)
{
INT32 deviceID;
INT32 i, j;
if (key <= 0 || key >= NUMINPUTS)
{
return 0;
}
if (menu == false)
deviceID = cv_usejoystick[p].value;
if (menuPlayers > 0)
{
// Try every device that does NOT belong to another player.
for (i = MAXDEVICES-1; i >= 0; i--)
{
if (i == deviceID)
{
// We've tried this one multiple times :V
continue;
}
if (menuPlayers > 1)
{
for (j = 1; j < menuPlayers; j++)
{
if (i == cv_usejoystick[j].value)
{
break;
}
}
if (j < menuPlayers)
{
// This one's taken.
continue;
}
}
if (gamekeydown[i][key] != 0)
{
return gamekeydown[i][key];
}
}
}
else
{
deviceID = cv_usejoystick[p].value;
if (deviceID < 0 || deviceID >= MAXDEVICES)
{
// Device is unset
return 0;
}
return gamekeydown[deviceID][key];
}
else
{
// Use keyboard as alternative for P1 menu.
return gamekeydown[0][key];
}
return 0;
}
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean menu)
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers)
{
INT32 i;
INT32 deadzone = 0;
@ -713,15 +745,12 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean menu)
}
}
#if 1
(void)menu;
#else
if (p == 0 && menu == true)
if (menuPlayers != 0)
{
// We don't want menus to become unnavigable if people unbind
// all of their controls, so use the default control scheme in
// this scenario.
// all of their controls, so we do several things in this scenario.
// First: check the same device, but with default binds.
for (i = 0; i < MAXINPUTMAPPING; i++)
{
INT32 key = gamecontroldefault[gc][i];
@ -732,22 +761,34 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean menu)
continue;
}
value = KeyValue(p, key, true);
value = KeyValue(p, key, false);
if (value >= deadzone)
{
return value;
}
if (p == 0 && menuPlayers == 1)
{
// Second: if we're Player 1 and there are no other players,
// then we can use keyboard defaults as a final resort.
value = KeyValue(p, key, menuPlayers);
if (value >= deadzone)
{
return value;
}
}
}
}
#endif
return 0;
}
boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean menu)
boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers)
{
return (G_PlayerInputAnalog(p, gc, menu) != 0);
return (G_PlayerInputAnalog(p, gc, menuPlayers) != 0);
}
// Take a magnitude of two axes, and adjust it to take out the deadzone
@ -867,7 +908,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
return;
}
joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_right, false) - G_PlayerInputAnalog(forplayer, gc_left, false);
joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_right, 0) - G_PlayerInputAnalog(forplayer, gc_left, 0);
joystickvector.yaxis = 0;
G_HandleAxisDeadZone(forplayer, &joystickvector);
@ -875,7 +916,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_down, false) - G_PlayerInputAnalog(forplayer, gc_up, false);
joystickvector.yaxis = G_PlayerInputAnalog(forplayer, gc_down, 0) - G_PlayerInputAnalog(forplayer, gc_up, 0);
if (encoremode)
{
@ -892,12 +933,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls
{
if (G_PlayerInputDown(forplayer, gc_a, false))
if (G_PlayerInputDown(forplayer, gc_a, 0))
{
cmd->buttons |= BT_ACCELERATE;
}
if (G_PlayerInputDown(forplayer, gc_b, false))
if (G_PlayerInputDown(forplayer, gc_b, 0))
{
cmd->buttons |= BT_BRAKE;
}
@ -915,14 +956,14 @@ 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_a, false);
fixed_t value = G_PlayerInputAnalog(forplayer, gc_a, 0);
if (value != 0)
{
cmd->buttons |= BT_ACCELERATE;
forward += ((value * MAXPLMOVE) >> 10);
}
value = G_PlayerInputAnalog(forplayer, gc_b, false);
value = G_PlayerInputAnalog(forplayer, gc_b, 0);
if (value != 0)
{
cmd->buttons |= BT_BRAKE;
@ -942,19 +983,19 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
}
// fire with any button/key
if (G_PlayerInputDown(forplayer, gc_c, false))
if (G_PlayerInputDown(forplayer, gc_c, 0))
{
cmd->buttons |= BT_ATTACK;
}
// drift with any button/key
if (G_PlayerInputDown(forplayer, gc_x, false))
if (G_PlayerInputDown(forplayer, gc_x, 0))
{
cmd->buttons |= BT_DRIFT;
}
// rear view with any button/key
if (G_PlayerInputDown(forplayer, gc_y, false))
if (G_PlayerInputDown(forplayer, gc_y, 0))
{
cmd->buttons |= BT_LOOKBACK;
}

View file

@ -88,8 +88,8 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming);
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean menu);
boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean menu);
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers);
boolean G_PlayerInputDown(UINT8 p, INT32 gc, UINT8 menuPlayers);
//
// GAME

View file

@ -134,6 +134,7 @@ typedef struct menu_s
void (*drawroutine)(void); // draw routine
void (*tickroutine)(void); // ticker routine
void (*initroutine)(void); // called when starting a new menu
boolean (*quitroutine)(void); // called before quit a menu return true if we can
boolean (*inputroutine)(INT32); // if set, called every frame in the input handler. Returning true overwrites normal input handling.
} menu_t;
@ -475,7 +476,8 @@ typedef enum
} splitscreencvars_t;
extern consvar_t *setup_playercvars[MAXSPLITSCREENPLAYERS][SPLITCV_MAX];
void M_CharacterSelectInit(INT32 choice);
void M_CharacterSelectInit(void);
void M_CharacterSelect(INT32 choice);
boolean M_CharacterSelectHandler(INT32 choice);
void M_CharacterSelectTick(void);
boolean M_CharacterSelectQuit(void);
@ -783,6 +785,7 @@ void M_DrawAddons(void);
M_DrawGenericMenu,\
NULL,\
NULL,\
NULL,\
NULL\
}
@ -799,6 +802,7 @@ void M_DrawAddons(void);
M_DrawKartGamemodeMenu,\
NULL,\
NULL,\
NULL,\
NULL\
}
@ -814,6 +818,7 @@ void M_DrawAddons(void);
M_DrawImageDef,\
NULL,\
NULL,\
NULL,\
NULL\
}

View file

@ -29,7 +29,7 @@ menuitem_t MainMenu[] =
{
{IT_STRING | IT_CALL, "Play",
"Cut to the chase and start the race!", NULL,
M_CharacterSelectInit, 0, 0},
M_CharacterSelect, 0, 0},
{IT_STRING | IT_CALL, "Extras",
"Check out some bonus features.", "MENUI001",
@ -65,6 +65,7 @@ menu_t PLAY_CharSelectDef = {
0, 0,
M_DrawCharacterSelect,
M_CharacterSelectTick,
M_CharacterSelectInit,
M_CharacterSelectQuit,
M_CharacterSelectHandler
};
@ -155,6 +156,7 @@ menu_t PLAY_RaceDifficultyDef = {
M_DrawRaceDifficulty,
NULL,
NULL,
NULL,
NULL
};
@ -175,6 +177,7 @@ menu_t PLAY_CupSelectDef = {
M_DrawCupSelect,
M_CupSelectTick,
NULL,
NULL,
NULL
};
@ -194,6 +197,7 @@ menu_t PLAY_LevelSelectDef = {
M_DrawLevelSelect,
M_LevelSelectTick,
NULL,
NULL,
NULL
};
@ -216,6 +220,7 @@ menu_t PLAY_TimeAttackDef = {
M_DrawTimeAttack,
NULL,
NULL,
NULL,
NULL
};
@ -259,6 +264,7 @@ menu_t PLAY_MP_OptSelectDef = {
M_DrawMPOptSelect,
M_MPOptSelectTick,
NULL,
NULL,
NULL
};
@ -294,6 +300,7 @@ menu_t PLAY_MP_HostDef = {
-1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe
M_DrawMPHost,
M_MPOptSelectTick, // This handles the unfolding options
NULL,
M_MPResetOpts,
NULL
};
@ -330,6 +337,7 @@ menu_t PLAY_MP_JoinIPDef = {
-1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe
M_DrawMPJoinIP,
M_MPOptSelectTick, // This handles the unfolding options
NULL,
M_MPResetOpts,
M_JoinIPInputs
};
@ -351,6 +359,7 @@ menu_t PLAY_MP_RoomSelectDef = {
M_DrawMPRoomSelect,
M_MPRoomSelectTick,
NULL,
NULL,
NULL
};
@ -395,6 +404,7 @@ menu_t OPTIONS_MainDef = {
M_DrawOptions,
M_OptionsTick,
NULL,
NULL,
M_OptionsInputs
};
@ -457,6 +467,7 @@ menu_t OPTIONS_VideoDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_VideoModes[] = {
@ -478,6 +489,7 @@ menu_t OPTIONS_VideoModesDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#ifdef HWRENDER
@ -536,6 +548,7 @@ menu_t OPTIONS_VideoOGLDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#endif
@ -599,6 +612,7 @@ menu_t OPTIONS_SoundDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_HUD[] =
@ -654,6 +668,7 @@ menu_t OPTIONS_HUDDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_HUDOnline[] =
@ -703,6 +718,7 @@ menu_t OPTIONS_HUDOnlineDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
@ -756,6 +772,7 @@ menu_t OPTIONS_GameplayDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_GameplayItems[] =
@ -801,6 +818,7 @@ menu_t OPTIONS_GameplayItemsDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_Server[] =
@ -865,6 +883,7 @@ menu_t OPTIONS_ServerDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#ifndef NONET
@ -923,6 +942,7 @@ menu_t OPTIONS_ServerAdvancedDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#endif
@ -964,6 +984,7 @@ menu_t OPTIONS_DataDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_DataAddon[] =
@ -1010,6 +1031,7 @@ menu_t OPTIONS_DataAddonDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_DataScreenshot[] =
@ -1050,6 +1072,7 @@ menu_t OPTIONS_DataScreenshotDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
menuitem_t OPTIONS_DataReplay[] =
@ -1076,6 +1099,7 @@ menu_t OPTIONS_DataReplayDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#ifdef HAVE_DISCORDRPC
@ -1114,6 +1138,7 @@ menu_t OPTIONS_DataDiscordDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
#endif
@ -1147,6 +1172,7 @@ menu_t OPTIONS_DataEraseDef = {
M_OptionsTick,
NULL,
NULL,
NULL,
};
@ -1180,6 +1206,7 @@ menu_t EXTRAS_MainDef = {
M_DrawExtras,
M_ExtrasTick,
NULL,
NULL,
M_ExtrasInputs
};
@ -1204,6 +1231,7 @@ menu_t EXTRAS_ReplayHutDef =
0, 0,
M_DrawReplayHut,
NULL,
NULL,
M_QuitReplayHut,
NULL
};
@ -1236,6 +1264,7 @@ menu_t EXTRAS_ReplayStartDef =
M_DrawReplayStartMenu,
NULL,
NULL,
NULL,
NULL
};
@ -1276,7 +1305,7 @@ menuitem_t PAUSE_Main[] =
NULL, NULL, 0, 0},
{IT_STRING | IT_CALL, "PLAYER SETUP", "M_ICOCHR",
NULL, M_CharacterSelectInit, 0, 0},
NULL, M_CharacterSelect, 0, 0},
{IT_STRING | IT_CALL, "OPTIONS", "M_ICOOPT",
NULL, M_InitOptions, 0, 0},
@ -1296,6 +1325,7 @@ menu_t PAUSE_MainDef = {
M_DrawPause,
M_PauseTick,
NULL,
NULL,
M_PauseInputs
};
@ -1346,6 +1376,7 @@ menu_t PAUSE_PlaybackMenuDef = {
M_DrawPlaybackMenu,
NULL,
NULL,
NULL,
NULL
};
@ -1390,5 +1421,6 @@ menu_t MISC_AddonsDef = {
M_DrawAddons,
NULL,
NULL,
NULL,
NULL
};

View file

@ -862,7 +862,7 @@ boolean M_Responder(event_t *ev)
}
#endif
if (CON_Ready() == false && G_PlayerInputDown(0, gc_start, true) == true)
if (CON_Ready() == false && G_PlayerInputDown(0, gc_start, splitscreen + 1) == true)
{
if (chat_on)
{
@ -893,6 +893,13 @@ void M_StartControlPanel(void)
{
INT32 i;
memset(gamekeydown, 0, sizeof (gamekeydown));
memset(menucmd, 0, sizeof (menucmd));
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
menucmd[i].delay = MENUDELAYTIME;
}
// intro might call this repeatedly
if (menuactive)
{
@ -913,11 +920,6 @@ void M_StartControlPanel(void)
menuactive = true;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
menucmd[i].delay = MENUDELAYTIME;
}
if (demo.playback)
{
currentMenu = &PAUSE_PlaybackMenuDef;
@ -933,137 +935,6 @@ void M_StartControlPanel(void)
M_OpenPauseMenu();
}
#if 0
else if (modeattacking)
{
currentMenu = &MAPauseDef;
itemOn = mapause_continue;
}
else if (!(netgame || multiplayer)) // Single Player
{
if (gamestate != GS_LEVEL) // intermission, so gray out stuff.
SPauseMenu[spause_retry].status = IT_GRAYEDOUT;
else
{
//INT32 numlives = 2;
/*if (&players[consoleplayer])
{
numlives = players[consoleplayer].lives;
if (players[consoleplayer].playerstate != PST_LIVE)
++numlives;
}
// The list of things that can disable retrying is (was?) a little too complex
// for me to want to use the short if statement syntax
if (numlives <= 1 || G_IsSpecialStage(gamemap))
SPauseMenu[spause_retry].status = (IT_GRAYEDOUT);
else*/
SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL);
}
currentMenu = &SPauseDef;
itemOn = spause_continue;
}
else // multiplayer
{
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
MPauseMenu[mpause_addons].status = IT_DISABLED;
MPauseMenu[mpause_scramble].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit3].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit4].status = IT_DISABLED;
MPauseMenu[mpause_spectate].status = IT_DISABLED;
MPauseMenu[mpause_entergame].status = IT_DISABLED;
MPauseMenu[mpause_canceljoin].status = IT_DISABLED;
MPauseMenu[mpause_switchteam].status = IT_DISABLED;
MPauseMenu[mpause_switchspectate].status = IT_DISABLED;
MPauseMenu[mpause_psetup].status = IT_DISABLED;
MISC_ChangeTeamMenu[0].status = IT_DISABLED;
MISC_ChangeSpectateMenu[0].status = IT_DISABLED;
// Reset these in case splitscreen messes things up
MPauseMenu[mpause_switchteam].mvar1 = 48;
MPauseMenu[mpause_switchspectate].mvar1 = 48;
MPauseMenu[mpause_options].mvar1 = 64;
MPauseMenu[mpause_title].mvar1 = 80;
MPauseMenu[mpause_quit].mvar1 = 88;
Dummymenuplayer_OnChange();
if ((server || IsPlayerAdmin(consoleplayer)))
{
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
if (G_GametypeHasTeams())
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
}
if (splitscreen)
{
MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL;
MISC_ChangeTeamMenu[0].status = MISC_ChangeSpectateMenu[0].status = IT_STRING|IT_CVAR;
if (netgame)
{
if (G_GametypeHasTeams())
{
MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU;
MPauseMenu[mpause_switchteam].mvar1 += ((splitscreen+1) * 8);
MPauseMenu[mpause_options].mvar1 += 8;
MPauseMenu[mpause_title].mvar1 += 8;
MPauseMenu[mpause_quit].mvar1 += 8;
}
else if (G_GametypeHasSpectators())
{
MPauseMenu[mpause_switchspectate].status = IT_STRING | IT_SUBMENU;
MPauseMenu[mpause_switchspectate].mvar1 += ((splitscreen+1) * 8);
MPauseMenu[mpause_options].mvar1 += 8;
MPauseMenu[mpause_title].mvar1 += 8;
MPauseMenu[mpause_quit].mvar1 += 8;
}
}
if (splitscreen > 1)
{
MPauseMenu[mpause_psetupsplit3].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_options].mvar1 += 8;
MPauseMenu[mpause_title].mvar1 += 8;
MPauseMenu[mpause_quit].mvar1 += 8;
if (splitscreen > 2)
{
MPauseMenu[mpause_psetupsplit4].status = IT_STRING | IT_CALL;
MPauseMenu[mpause_options].mvar1 += 8;
MPauseMenu[mpause_title].mvar1 += 8;
MPauseMenu[mpause_quit].mvar1 += 8;
}
}
}
else
{
MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL;
if (G_GametypeHasTeams())
MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU;
else if (G_GametypeHasSpectators())
{
if (!players[consoleplayer].spectator)
MPauseMenu[mpause_spectate].status = IT_STRING | IT_CALL;
else if (players[consoleplayer].pflags & PF_WANTSTOJOIN)
MPauseMenu[mpause_canceljoin].status = IT_STRING | IT_CALL;
else
MPauseMenu[mpause_entergame].status = IT_STRING | IT_CALL;
}
else // in this odd case, we still want something to be on the menu even if it's useless
MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT;
}
currentMenu = &MPauseDef;
itemOn = mpause_continue;
}
#endif
CON_ToggleOff(); // move away console
}
@ -1104,11 +975,6 @@ void M_SetupNextMenu(menu_t *menudef, boolean notransition)
{
INT16 i;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
menucmd[i].delay = MENUDELAYTIME;
}
if (!notransition)
{
if (currentMenu->transitionID == menudef->transitionID
@ -1139,6 +1005,16 @@ void M_SetupNextMenu(menu_t *menudef, boolean notransition)
return; // we can't quit this menu (also used to set parameter from the menu)
}
if (menudef->initroutine != NULL
#if 0
&& currentMenu != menudef // Unsure if we need this...
#endif
)
{
// Moving to a new menu, reinitialize.
menudef->initroutine();
}
currentMenu = menudef;
itemOn = currentMenu->lastOn;
@ -1209,27 +1085,29 @@ static void M_SetMenuDelay(UINT8 i)
static void M_UpdateMenuCMD(UINT8 i)
{
UINT8 mp = max(1, setup_numplayers);
menucmd[i].dpad_ud = 0;
menucmd[i].dpad_lr = 0;
menucmd[i].buttonsHeld = menucmd[i].buttons;
menucmd[i].buttons = 0;
if (G_PlayerInputDown(i, gc_up, true)) { menucmd[i].dpad_ud--; }
if (G_PlayerInputDown(i, gc_down, true)) { menucmd[i].dpad_ud++; }
if (G_PlayerInputDown(i, gc_up, mp)) { menucmd[i].dpad_ud--; }
if (G_PlayerInputDown(i, gc_down, mp)) { menucmd[i].dpad_ud++; }
if (G_PlayerInputDown(i, gc_left, true)) { menucmd[i].dpad_lr--; }
if (G_PlayerInputDown(i, gc_right, true)) { menucmd[i].dpad_lr++; }
if (G_PlayerInputDown(i, gc_left, mp)) { menucmd[i].dpad_lr--; }
if (G_PlayerInputDown(i, gc_right, mp)) { menucmd[i].dpad_lr++; }
if (G_PlayerInputDown(i, gc_a, true)) { menucmd[i].buttons |= MBT_A; }
if (G_PlayerInputDown(i, gc_b, true)) { menucmd[i].buttons |= MBT_B; }
if (G_PlayerInputDown(i, gc_c, true)) { menucmd[i].buttons |= MBT_C; }
if (G_PlayerInputDown(i, gc_x, true)) { menucmd[i].buttons |= MBT_X; }
if (G_PlayerInputDown(i, gc_y, true)) { menucmd[i].buttons |= MBT_Y; }
if (G_PlayerInputDown(i, gc_z, true)) { menucmd[i].buttons |= MBT_Z; }
if (G_PlayerInputDown(i, gc_l, true)) { menucmd[i].buttons |= MBT_L; }
if (G_PlayerInputDown(i, gc_r, true)) { menucmd[i].buttons |= MBT_R; }
if (G_PlayerInputDown(i, gc_start, true)) { menucmd[i].buttons |= MBT_START; }
if (G_PlayerInputDown(i, gc_a, mp)) { menucmd[i].buttons |= MBT_A; }
if (G_PlayerInputDown(i, gc_b, mp)) { menucmd[i].buttons |= MBT_B; }
if (G_PlayerInputDown(i, gc_c, mp)) { menucmd[i].buttons |= MBT_C; }
if (G_PlayerInputDown(i, gc_x, mp)) { menucmd[i].buttons |= MBT_X; }
if (G_PlayerInputDown(i, gc_y, mp)) { menucmd[i].buttons |= MBT_Y; }
if (G_PlayerInputDown(i, gc_z, mp)) { menucmd[i].buttons |= MBT_Z; }
if (G_PlayerInputDown(i, gc_l, mp)) { menucmd[i].buttons |= MBT_L; }
if (G_PlayerInputDown(i, gc_r, mp)) { menucmd[i].buttons |= MBT_R; }
if (G_PlayerInputDown(i, gc_start, mp)) { menucmd[i].buttons |= MBT_START; }
if (menucmd[i].dpad_ud == 0 && menucmd[i].dpad_lr == 0 && menucmd[i].buttons == 0)
{
@ -1262,6 +1140,12 @@ static void M_HandleMenuInput(void)
M_UpdateMenuCMD(i);
}
if (menuactive == false)
{
// We're not in the menu.
return;
}
// Handle menu-specific input handling. If this returns true, we skip regular input handling.
if (currentMenu->inputroutine)
{
@ -1385,7 +1269,7 @@ static void M_HandleMenuInput(void)
return;
}
else if ((menucmd[pid].buttons & MBT_A) || (menucmd[pid].buttons & MBT_X) /*|| (menucmd[pid].buttons & MBT_START)*/)
else if (M_MenuButtonPressed(pid, MBT_A) || M_MenuButtonPressed(pid, MBT_X) /*|| M_MenuButtonPressed(pid, MBT_START)*/)
{
noFurtherInput = true;
currentMenu->lastOn = itemOn;
@ -1424,13 +1308,13 @@ static void M_HandleMenuInput(void)
M_SetMenuDelay(pid);
return;
}
else if ((menucmd[pid].buttons & MBT_B) || (menucmd[pid].buttons & MBT_Y))
else if (M_MenuButtonPressed(pid, MBT_B) || M_MenuButtonPressed(pid, MBT_Y))
{
M_GoBack(0);
M_SetMenuDelay(pid);
return;
}
else if ((menucmd[pid].buttons & MBT_C) || (menucmd[pid].buttons & MBT_Z))
else if (M_MenuButtonPressed(pid, MBT_C) || M_MenuButtonPressed(pid, MBT_Z))
{
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
@ -1517,20 +1401,17 @@ void M_Ticker(void)
}
}
if (menuactive == true)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
if (menucmd[i].delay > 0)
{
if (menucmd[i].delay > 0)
{
menucmd[i].delay--;
}
menucmd[i].delay--;
}
}
if (noFurtherInput == false)
{
M_HandleMenuInput();
}
if (noFurtherInput == false)
{
M_HandleMenuInput();
}
if (currentMenu->tickroutine)
@ -1624,16 +1505,17 @@ static menuitem_t MessageMenu[] =
menu_t MessageDef =
{
1, // # of menu items
NULL, // previous menu (TO HACK)
0, // lastOn, flags (TO HACK)
MessageMenu, // menuitem_t ->
0, 0, // x, y (TO HACK)
1, // # of menu items
NULL, // previous menu (TO HACK)
0, // lastOn, flags (TO HACK)
MessageMenu, // menuitem_t ->
0, 0, // x, y (TO HACK)
0, 0, // extra1, extra2
0, 0, // transition tics
M_DrawMessageMenu, // drawing routine ->
NULL, // ticker routine
NULL, // quit routine
0, 0, // transition tics
M_DrawMessageMenu, // drawing routine ->
NULL, // ticker routine
NULL, // init routine
NULL, // quit routine
NULL // input routine
};
@ -1886,14 +1768,20 @@ struct setup_chargrid_s setup_chargrid[9][9];
setup_player_t setup_player[MAXSPLITSCREENPLAYERS];
struct setup_explosions_s setup_explosions[48];
UINT8 setup_numplayers = 0;
UINT8 setup_numplayers = 0; // This variable is very important, it was extended to determine how many players exist in ALL menus.
tic_t setup_animcounter = 0;
void M_CharacterSelectInit(INT32 choice)
void M_CharacterSelectInit(void)
{
UINT8 i, j;
(void)choice;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
// Un-set devices for other players.
CV_SetValue(&cv_usejoystick[i], -1);
CONS_Printf("Device for %d set to %d\n", i, -1);
}
CONS_Printf("========\n");
memset(setup_chargrid, -1, sizeof(setup_chargrid));
for (i = 0; i < 9; i++)
@ -1931,7 +1819,11 @@ void M_CharacterSelectInit(INT32 choice)
}
}
}
}
void M_CharacterSelect(INT32 choice)
{
(void)choice;
PLAY_CharSelectDef.prevMenu = currentMenu;
M_SetupNextMenu(&PLAY_CharSelectDef, false);
}
@ -1983,7 +1875,7 @@ static void M_SetupReadyExplosions(setup_player_t *p)
}
}
static boolean M_DeviceAvailable(UINT8 deviceID, UINT8 numPlayers)
static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers)
{
INT32 i;
@ -2006,12 +1898,12 @@ static boolean M_DeviceAvailable(UINT8 deviceID, UINT8 numPlayers)
return true;
}
static void M_HandlePressStart(setup_player_t *p, UINT8 num)
static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
{
INT32 i, j;
// Detect B press first ... this means P1 can actually exit out of the menu.
if (menucmd[num].buttons & MBT_B)
if (M_MenuButtonPressed(num, MBT_B) || M_MenuButtonPressed(num, MBT_Y))
{
M_SetMenuDelay(num);
@ -2019,66 +1911,67 @@ static void M_HandlePressStart(setup_player_t *p, UINT8 num)
{
// We're done here.
M_GoBack(0);
return;
return true;
}
// Don't allow this press to ever count as "start".
return;
}
// Ensure their device is unset
if (cv_usejoystick[num].value != -1)
{
CV_SetValue(&cv_usejoystick[num], -1);
return false;
}
if (num != setup_numplayers)
{
// Only detect devices for the last player.
return;
return false;
}
// Now detect new devices trying to join.
for (i = 0; i < MAXDEVICES; i++)
{
if (deviceResponding[i] == false)
if (deviceResponding[i] != true)
{
// No buttons are being pushed.
continue;
}
if (M_DeviceAvailable(i, num) == true)
if (M_DeviceAvailable(i, setup_numplayers) == true)
{
// Available!! Let's use this one!!
CV_SetValue(&cv_usejoystick[num], i);
CONS_Printf("Device for %d set to %d\n", num, i);
CONS_Printf("========\n");
for (j = num+1; j < MAXSPLITSCREENPLAYERS; j++)
{
if (cv_usejoystick[j].value == i)
{
// Un-set devices for other players.
CV_SetValue(&cv_usejoystick[j], -1);
CONS_Printf("Device for %d set to %d\n", j, -1);
}
// Prevent excess presses for new players.
setup_player[j].delay = TICRATE;
// Un-set devices for other players.
CV_SetValue(&cv_usejoystick[j], -1);
CONS_Printf("Device for %d set to %d\n", j, -1);
}
CONS_Printf("========\n");
setup_numplayers++;
//setup_numplayers++;
p->mdepth = CSSTEP_CHARS;
S_StartSound(NULL, sfx_s3k65);
// Prevent quick presses
p->delay = MENUDELAYTIME;
M_SetMenuDelay(num);
// Prevent quick presses for multiple players
for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
{
setup_player[j].delay = MENUDELAYTIME;
M_SetMenuDelay(j);
menucmd[j].buttonsHeld |= (MBT_B|MBT_Y);
}
memset(deviceResponding, false, sizeof(deviceResponding));
return true;
}
}
return false;
}
static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
static boolean M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
{
INT32 i;
if (menucmd[num].dpad_ud > 0)
{
p->gridy++;
@ -2113,7 +2006,7 @@ static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
M_SetMenuDelay(num);
}
if ((menucmd[num].buttons & MBT_A) || (menucmd[num].buttons & MBT_X) /*|| (menucmd[num].buttons & MBT_START)*/)
if (M_MenuButtonPressed(num, MBT_A) || M_MenuButtonPressed(num, MBT_X) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{
if (setup_chargrid[p->gridx][p->gridy].numskins == 0)
{
@ -2131,12 +2024,22 @@ static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
M_SetMenuDelay(num);
}
else if ((menucmd[num].buttons & MBT_B) || (menucmd[num].buttons & MBT_Y))
else if (M_MenuButtonPressed(num, MBT_B) || M_MenuButtonPressed(num, MBT_Y))
{
if (num == setup_numplayers-1)
{
p->mdepth = CSSTEP_NONE;
S_StartSound(NULL, sfx_s3k5b);
// Prevent quick presses for multiple players
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
setup_player[i].delay = MENUDELAYTIME;
M_SetMenuDelay(i);
menucmd[i].buttonsHeld |= (MBT_B|MBT_Y);
}
return true;
}
else
{
@ -2145,6 +2048,8 @@ static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
M_SetMenuDelay(num);
}
return false;
}
static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
@ -2170,13 +2075,13 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3kc3s);
}
if ((menucmd[num].buttons & MBT_A) || (menucmd[num].buttons & MBT_X) /*|| (menucmd[num].buttons & MBT_START)*/)
if (M_MenuButtonPressed(num, MBT_A) || M_MenuButtonPressed(num, MBT_X) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{
p->mdepth = CSSTEP_COLORS;
S_StartSound(NULL, sfx_s3k63);
M_SetMenuDelay(num);
}
else if ((menucmd[num].buttons & MBT_B) || (menucmd[num].buttons & MBT_Y))
else if (M_MenuButtonPressed(num, MBT_B) || M_MenuButtonPressed(num, MBT_Y))
{
p->mdepth = CSSTEP_CHARS;
S_StartSound(NULL, sfx_s3k5b);
@ -2205,7 +2110,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
}
if ((menucmd[num].buttons & MBT_A) || (menucmd[num].buttons & MBT_X) /*|| (menucmd[num].buttons & MBT_START)*/)
if (M_MenuButtonPressed(num, MBT_A) || M_MenuButtonPressed(num, MBT_X) /*|| M_MenuButtonPressed(num, MBT_START)*/)
{
p->mdepth = CSSTEP_READY;
p->delay = TICRATE;
@ -2213,7 +2118,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3k4e);
M_SetMenuDelay(num);
}
else if ((menucmd[num].buttons & MBT_B) || (menucmd[num].buttons & MBT_Y))
else if (M_MenuButtonPressed(num, MBT_B) || M_MenuButtonPressed(num, MBT_Y))
{
if (setup_chargrid[p->gridx][p->gridy].numskins == 1)
p->mdepth = CSSTEP_CHARS; // Skip clones menu
@ -2226,23 +2131,24 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
boolean M_CharacterSelectHandler(INT32 choice)
{
UINT8 i;
INT32 i;
(void)choice;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
for (i = MAXSPLITSCREENPLAYERS-1; i >= 0; i--)
{
setup_player_t *p = &setup_player[i];
boolean playersChanged = false;
if (p->delay == 0 && menucmd[i].delay == 0)
{
switch (p->mdepth)
{
case CSSTEP_NONE: // Enter Game
M_HandlePressStart(p, i);
playersChanged = M_HandlePressStart(p, i);
break;
case CSSTEP_CHARS: // Character Select grid
M_HandleCharacterGrid(p, i);
playersChanged = M_HandleCharacterGrid(p, i);
break;
case CSSTEP_ALTS: // Select clone
M_HandleCharRotate(p, i);
@ -2252,7 +2158,7 @@ boolean M_CharacterSelectHandler(INT32 choice)
break;
case CSSTEP_READY:
default: // Unready
if (G_PlayerInputDown(i, gc_b, true) == true)
if (M_MenuButtonPressed(i, MBT_B) || M_MenuButtonPressed(i, MBT_Y))
{
p->mdepth = CSSTEP_COLORS;
S_StartSound(NULL, sfx_s3k5b);
@ -2266,7 +2172,14 @@ boolean M_CharacterSelectHandler(INT32 choice)
p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum];
if (p->mdepth < CSSTEP_COLORS)
{
p->color = skins[p->skin].prefcolor;
}
if (playersChanged == true)
{
break;
}
}
// Setup new numplayers
@ -2359,7 +2272,6 @@ void M_CharacterSelectTick(void)
if (setupnext && setup_numplayers > 0)
{
// Selecting from the menu
if (gamestate == GS_MENU)
{
@ -2406,7 +2318,6 @@ void M_CharacterSelectTick(void)
boolean M_CharacterSelectQuit(void)
{
M_CharacterSelectInit(0);
return true;
}
@ -3674,9 +3585,6 @@ void M_OpenPauseMenu(void)
PAUSE_Main[mpause_entergame].status = IT_STRING | IT_CALL;
}
}
}
void M_QuitPauseMenu(void)

View file

@ -684,7 +684,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_y, false))
if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && G_PlayerInputDown(0, gc_y, 0))
demo.savemode = DSM_TITLEENTRY;
}
else if (demo.playback) // Use Ghost data for consistency checks.

View file

@ -619,7 +619,7 @@ void Y_Ticker(void)
if (demo.recording)
{
if (demo.savemode == DSM_NOTSAVING && G_PlayerInputDown(0, gc_y, false))
if (demo.savemode == DSM_NOTSAVING && G_PlayerInputDown(0, gc_y, 0))
demo.savemode = DSM_TITLEENTRY;
if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE)
@ -1476,13 +1476,13 @@ void Y_VoteTicker(void)
&& !voteclient.playerinfo[i].delay
&& pickedvote == -1 && votes[p] == -1)
{
if (G_PlayerInputDown(i, gc_up, false))
if (G_PlayerInputDown(i, gc_up, 0))
{
voteclient.playerinfo[i].selection--;
pressed = true;
}
if (G_PlayerInputDown(i, gc_down, false) && pressed == false)
if (G_PlayerInputDown(i, gc_down, 0) && pressed == false)
{
voteclient.playerinfo[i].selection++;
pressed = true;
@ -1493,7 +1493,7 @@ void Y_VoteTicker(void)
if (voteclient.playerinfo[i].selection > 3)
voteclient.playerinfo[i].selection = 0;
if (G_PlayerInputDown(i, gc_a, false) && pressed == false)
if (G_PlayerInputDown(i, gc_a, 0) && pressed == false)
{
D_ModifyClientVote(consoleplayer, voteclient.playerinfo[i].selection, i);
pressed = true;