Add menucmd system

Allows menu input delays to feel sorta similar to how they did before ... maybe  could be adjusted further, since it feels just a tad bit touchy to me, but it's much better than before when it was a static value.
This commit is contained in:
Sally Coolatta 2021-12-06 14:53:30 -05:00
parent d2e26bbc86
commit ecffa90949
2 changed files with 192 additions and 78 deletions

View file

@ -335,8 +335,32 @@ extern INT16 skullAnimCounter; // skull animation counter
extern INT32 menuKey; // keyboard key pressed for menu extern INT32 menuKey; // keyboard key pressed for menu
#define MENUDELAYTIME 3 // TODO: recreate how old input holding worked #define MENUDELAYTIME 7
extern INT16 menuInputDelay;
typedef enum
{
MBT_A = 1,
MBT_B = 1<<1,
MBT_C = 1<<2,
MBT_X = 1<<3,
MBT_Y = 1<<4,
MBT_Z = 1<<5,
MBT_L = 1<<6,
MBT_R = 1<<7,
MBT_START = 1<<8
} menuButtonCode_t;
typedef struct menucmd_s
{
SINT8 dpad_ud; // up / down dpad
SINT8 dpad_lr; // left / right
UINT32 buttons; // buttons
UINT32 buttonsHeld; // prev frame's buttons
UINT16 delay; // menu wait
UINT32 delayCount; // num times ya did menu wait (to make the wait shorter each time)
} menucmd_t;
extern menucmd_t menucmd[MAXSPLITSCREENPLAYERS];
extern struct menutransition_s { extern struct menutransition_s {
INT16 tics; INT16 tics;
@ -358,6 +382,7 @@ void Addons_option_Onchange(void);
void M_SortServerList(void); void M_SortServerList(void);
boolean M_Responder(event_t *ev); boolean M_Responder(event_t *ev);
boolean M_MenuButtonPressed(UINT8 pid, UINT32 bt);
void M_StartControlPanel(void); void M_StartControlPanel(void);
void M_ClearMenus(boolean callexitmenufunc); void M_ClearMenus(boolean callexitmenufunc);
void M_SelectableClearMenus(INT32 choice); void M_SelectableClearMenus(INT32 choice);
@ -382,20 +407,22 @@ void M_InitPlayerSetupColors(void);
void M_FreePlayerSetupColors(void); void M_FreePlayerSetupColors(void);
// If you want to waste a bunch of memory for a limit no one will hit, feel free to boost this to MAXSKINS :P // If you want to waste a bunch of memory for a limit no one will hit, feel free to boost this to MAXSKINS :P
// I figure this will be enough clone characters to fit onto the character select. // I figure this will be enough clone characters to fit onto one grid space.
// (If someone runs into it after release I'll probably boost it, though.) #define MAXCLONES MAXSKINS/8
#define MAXCLONES MAXSKINS/16
extern struct setup_chargrid_s { extern struct setup_chargrid_s {
SINT8 skinlist[MAXCLONES]; SINT8 skinlist[MAXCLONES];
UINT8 numskins; UINT8 numskins;
} setup_chargrid[9][9]; } setup_chargrid[9][9];
#define CSSTEP_NONE 0 typedef enum
#define CSSTEP_CHARS 1 {
#define CSSTEP_ALTS 2 CSSTEP_NONE = 0,
#define CSSTEP_COLORS 3 CSSTEP_CHARS,
#define CSSTEP_READY 4 CSSTEP_ALTS,
CSSTEP_COLORS,
CSSTEP_READY
} setup_mdepth_t;
typedef struct setup_player_s typedef struct setup_player_s
{ {

View file

@ -94,7 +94,7 @@ INT16 skullAnimCounter = 8; // skull animation counter
struct menutransition_s menutransition; // Menu transition properties struct menutransition_s menutransition; // Menu transition properties
INT32 menuKey = -1; // keyboard key pressed for menu INT32 menuKey = -1; // keyboard key pressed for menu
INT16 menuInputDelay = 0; // Delay before registering multiple inputs. menucmd_t menucmd[MAXSPLITSCREENPLAYERS];
// finish wipes between screens // finish wipes between screens
boolean menuwipe = false; boolean menuwipe = false;
@ -749,11 +749,6 @@ static void M_PrevOpt(void)
// //
// M_Responder // M_Responder
// //
static boolean M_BasicMenuInput(INT32 gc)
{
return G_PlayerInputDown(0, gc, true);
}
boolean M_Responder(event_t *ev) boolean M_Responder(event_t *ev)
{ {
menuKey = -1; menuKey = -1;
@ -844,7 +839,7 @@ boolean M_Responder(event_t *ev)
} }
#endif #endif
if (M_BasicMenuInput(gc_start) == true) if (G_PlayerInputDown(0, gc_start, true) == true)
{ {
if (chat_on) if (chat_on)
{ {
@ -873,6 +868,8 @@ boolean M_Responder(event_t *ev)
// //
void M_StartControlPanel(void) void M_StartControlPanel(void)
{ {
INT32 i;
// intro might call this repeatedly // intro might call this repeatedly
if (menuactive) if (menuactive)
{ {
@ -892,7 +889,11 @@ void M_StartControlPanel(void)
} }
menuactive = true; menuactive = true;
menuInputDelay = MENUDELAYTIME;
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
menucmd[i].delay = MENUDELAYTIME;
}
if (demo.playback) if (demo.playback)
{ {
@ -1080,7 +1081,10 @@ void M_SetupNextMenu(menu_t *menudef, boolean notransition)
{ {
INT16 i; INT16 i;
menuInputDelay = MENUDELAYTIME; for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
menucmd[i].delay = MENUDELAYTIME;
}
if (!notransition) if (!notransition)
{ {
@ -1164,24 +1168,90 @@ void M_GoBack(INT32 choice)
// //
// M_Ticker // M_Ticker
// //
static boolean M_HandleMenuInput(void) static void M_SetMenuDelay(UINT8 i)
{ {
void (*routine)(INT32 choice); // for some casting problem menucmd[i].delayCount++;
if (menucmd[i].delayCount < 1)
{
// Shouldn't happen, but for safety.
menucmd[i].delayCount = 1;
}
if (menuInputDelay > 0) menucmd[i].delay = (MENUDELAYTIME / menucmd[i].delayCount);
if (menucmd[i].delay < 1)
{
menucmd[i].delay = 1;
}
}
static void M_UpdateMenuCMD(UINT8 i)
{
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_left, true)) { menucmd[i].dpad_lr--; }
if (G_PlayerInputDown(i, gc_right, true)) { 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 (menucmd[i].dpad_ud == 0 && menucmd[i].dpad_lr == 0 && menucmd[i].buttons == 0)
{
// Reset delay count with no buttons.
menucmd[i].delayCount = 0;
}
}
boolean M_MenuButtonPressed(UINT8 pid, UINT32 bt)
{
if (menucmd[pid].buttonsHeld & bt)
{ {
return false; return false;
} }
return (menucmd[pid].buttons & bt);
}
static void M_HandleMenuInput(void)
{
void (*routine)(INT32 choice); // for some casting problem
INT32 i;
UINT8 pid = 0; // todo: Add ability for any splitscreen player to bring up the menu.
SINT8 lr = 0, ud = 0;
// Update menu CMD
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
M_UpdateMenuCMD(i);
}
// Handle menu-specific input handling. If this returns true, we skip regular input handling. // Handle menu-specific input handling. If this returns true, we skip regular input handling.
if (currentMenu->inputroutine) if (currentMenu->inputroutine)
{ {
if (currentMenu->inputroutine(menuKey)) if (currentMenu->inputroutine(menuKey))
{ {
return false; return;
} }
} }
if (menucmd[pid].delay > 0)
{
return;
}
routine = currentMenu->menuitems[itemOn].itemaction; routine = currentMenu->menuitems[itemOn].itemaction;
// Handle menuitems which need a specific key handling // Handle menuitems which need a specific key handling
@ -1193,7 +1263,7 @@ static boolean M_HandleMenuInput(void)
if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER)
{ {
routine(-1); routine(-1);
return true; return;
} }
*/ */
@ -1202,7 +1272,7 @@ static boolean M_HandleMenuInput(void)
{ {
if (currentMenu->menuitems[itemOn].mvar1 != MM_EVENTHANDLER) if (currentMenu->menuitems[itemOn].mvar1 != MM_EVENTHANDLER)
{ {
if (M_BasicMenuInput(gc_a) || M_BasicMenuInput(gc_b) || M_BasicMenuInput(gc_start)) if (menucmd[pid].buttons != 0 && menucmd[pid].buttonsHeld == 0)
{ {
if (routine) if (routine)
{ {
@ -1211,10 +1281,11 @@ static boolean M_HandleMenuInput(void)
M_StopMessage(0); M_StopMessage(0);
noFurtherInput = true; noFurtherInput = true;
return true; M_SetMenuDelay(pid);
return;
} }
return false; return;
} }
else else
{ {
@ -1226,7 +1297,7 @@ static boolean M_HandleMenuInput(void)
} }
#endif #endif
return false; return;
} }
} }
@ -1244,44 +1315,53 @@ static boolean M_HandleMenuInput(void)
} }
} }
lr = menucmd[pid].dpad_lr;
ud = menucmd[pid].dpad_ud;
// LR does nothing in the default menu, just remap as dpad.
if (menucmd[pid].buttons & MBT_L) { lr--; }
if (menucmd[pid].buttons & MBT_R) { lr++; }
// Keys usable within menu // Keys usable within menu
if (M_BasicMenuInput(gc_down) == true) if (ud > 0)
{ {
M_NextOpt(); M_NextOpt();
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
return true; M_SetMenuDelay(pid);
return;
} }
else if (M_BasicMenuInput(gc_up) == true) else if (ud < 0)
{ {
M_PrevOpt(); M_PrevOpt();
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
return true; M_SetMenuDelay(pid);
return;
} }
else if (M_BasicMenuInput(gc_left) == true) else if (lr < 0)
{ {
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{ {
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
routine(0); routine(0);
return true; M_SetMenuDelay(pid);
} }
return false; return;
} }
else if (M_BasicMenuInput(gc_right) == true) else if (lr > 0)
{ {
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{ {
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
routine(1); routine(1);
return true; M_SetMenuDelay(pid);
} }
return false; return;
} }
else if (M_BasicMenuInput(gc_a) == true) else if ((menucmd[pid].buttons & MBT_A) || (menucmd[pid].buttons & MBT_X) /*|| (menucmd[pid].buttons & MBT_START)*/)
{ {
noFurtherInput = true; noFurtherInput = true;
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
@ -1297,7 +1377,7 @@ static boolean M_HandleMenuInput(void)
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods) if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods)
{ {
M_StartMessage(M_GetText("This cannot be done with complex addons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("This cannot be done with complex addons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
return true; return;
} }
} }
@ -1317,14 +1397,16 @@ static boolean M_HandleMenuInput(void)
} }
} }
return true; M_SetMenuDelay(pid);
return;
} }
else if (M_BasicMenuInput(gc_b) == true) else if ((menucmd[pid].buttons & MBT_B) || (menucmd[pid].buttons & MBT_Y))
{ {
M_GoBack(0); M_GoBack(0);
return true; M_SetMenuDelay(pid);
return;
} }
else if (M_BasicMenuInput(gc_c) == true) else if ((menucmd[pid].buttons & MBT_C) || (menucmd[pid].buttons & MBT_Z))
{ {
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
@ -1340,23 +1422,26 @@ static boolean M_HandleMenuInput(void)
*/ */
) )
{ {
return true; return;
} }
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
routine(-1); routine(-1);
return true; M_SetMenuDelay(pid);
return;
} }
return false; return;
} }
return false; return;
} }
void M_Ticker(void) void M_Ticker(void)
{ {
INT32 i;
if (menutransition.tics != 0 || menutransition.dest != 0) if (menutransition.tics != 0 || menutransition.dest != 0)
{ {
noFurtherInput = true; noFurtherInput = true;
@ -1408,17 +1493,17 @@ void M_Ticker(void)
} }
} }
if (menuInputDelay > 0) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{ {
menuInputDelay--; if (menucmd[i].delay > 0)
{
menucmd[i].delay--;
}
} }
if (noFurtherInput == false) if (noFurtherInput == false)
{ {
if (M_HandleMenuInput() == true) M_HandleMenuInput();
{
menuInputDelay = MENUDELAYTIME;
}
} }
if (currentMenu->tickroutine) if (currentMenu->tickroutine)
@ -1869,39 +1954,41 @@ static void M_SetupReadyExplosions(setup_player_t *p)
static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num) static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
{ {
if (G_PlayerInputDown(num, gc_down, true) == true) if (menucmd[num].dpad_ud > 0)
{ {
p->gridy++; p->gridy++;
if (p->gridy > 8) if (p->gridy > 8)
p->gridy = 0; p->gridy = 0;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_up, true) == true) else if (menucmd[num].dpad_ud < 0)
{ {
p->gridy--; p->gridy--;
if (p->gridy < 0) if (p->gridy < 0)
p->gridy = 8; p->gridy = 8;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_right, true) == true)
if (menucmd[num].dpad_lr > 0)
{ {
p->gridx++; p->gridx++;
if (p->gridx > 8) if (p->gridx > 8)
p->gridx = 0; p->gridx = 0;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_left, true) == true) else if (menucmd[num].dpad_lr < 0)
{ {
p->gridx--; p->gridx--;
if (p->gridx < 0) if (p->gridx < 0)
p->gridx = 8; p->gridx = 8;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_a, true) == true || G_PlayerInputDown(num, gc_start, true) == true)
if ((menucmd[num].buttons & MBT_A) || (menucmd[num].buttons & MBT_X) /*|| (menucmd[num].buttons & MBT_START)*/)
{ {
if (setup_chargrid[p->gridx][p->gridy].numskins == 0) if (setup_chargrid[p->gridx][p->gridy].numskins == 0)
{ {
@ -1917,9 +2004,9 @@ static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3k63); S_StartSound(NULL, sfx_s3k63);
} }
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_b, true) == true) else if ((menucmd[num].buttons & MBT_B) || (menucmd[num].buttons & MBT_Y))
{ {
if (num == setup_numplayers-1) if (num == setup_numplayers-1)
{ {
@ -1931,7 +2018,7 @@ static void M_HandleCharacterGrid(setup_player_t *p, UINT8 num)
S_StartSound(NULL, sfx_s3kb2); S_StartSound(NULL, sfx_s3kb2);
} }
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
} }
@ -1957,17 +2044,18 @@ static void M_HandleCharRotate(setup_player_t *p, UINT8 num)
p->delay = CSROTATETICS; p->delay = CSROTATETICS;
S_StartSound(NULL, sfx_s3kc3s); S_StartSound(NULL, sfx_s3kc3s);
} }
else if (G_PlayerInputDown(num, gc_a, true) == true || G_PlayerInputDown(num, gc_start, true) == true)
if (G_PlayerInputDown(num, gc_a, true) == true || G_PlayerInputDown(num, gc_start, true) == true)
{ {
p->mdepth = CSSTEP_COLORS; p->mdepth = CSSTEP_COLORS;
S_StartSound(NULL, sfx_s3k63); S_StartSound(NULL, sfx_s3k63);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_b, true) == true) else if (G_PlayerInputDown(num, gc_b, true) == true)
{ {
p->mdepth = CSSTEP_CHARS; p->mdepth = CSSTEP_CHARS;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
} }
@ -1979,7 +2067,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
if (p->color >= numskincolors) if (p->color >= numskincolors)
p->color = 1; p->color = 1;
p->rotate = CSROTATETICS; p->rotate = CSROTATETICS;
p->delay = MENUDELAYTIME; //CSROTATETICS M_SetMenuDelay(num); //CSROTATETICS
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
} }
else if (G_PlayerInputDown(num, gc_left, true) == true) else if (G_PlayerInputDown(num, gc_left, true) == true)
@ -1988,15 +2076,17 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
if (p->color < 1) if (p->color < 1)
p->color = numskincolors-1; p->color = numskincolors-1;
p->rotate = -CSROTATETICS; p->rotate = -CSROTATETICS;
p->delay = MENUDELAYTIME; //CSROTATETICS M_SetMenuDelay(num); //CSROTATETICS
S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s S_StartSound(NULL, sfx_s3k5b); //sfx_s3kc3s
} }
else if (G_PlayerInputDown(num, gc_a, true) == true || G_PlayerInputDown(num, gc_start, true) == true)
if (G_PlayerInputDown(num, gc_a, true) == true || G_PlayerInputDown(num, gc_start, true) == true)
{ {
p->mdepth = CSSTEP_READY; p->mdepth = CSSTEP_READY;
p->delay = TICRATE; p->delay = TICRATE;
M_SetupReadyExplosions(p); M_SetupReadyExplosions(p);
S_StartSound(NULL, sfx_s3k4e); S_StartSound(NULL, sfx_s3k4e);
M_SetMenuDelay(num);
} }
else if (G_PlayerInputDown(num, gc_b, true) == true) else if (G_PlayerInputDown(num, gc_b, true) == true)
{ {
@ -2005,7 +2095,7 @@ static void M_HandleColorRotate(setup_player_t *p, UINT8 num)
else else
p->mdepth = CSSTEP_ALTS; p->mdepth = CSSTEP_ALTS;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(num);
} }
} }
@ -2022,7 +2112,7 @@ boolean M_CharacterSelectHandler(INT32 choice)
if (i > 0) if (i > 0)
break; // temp break; // temp
if (p->delay == 0) if (p->delay == 0 && menucmd[i].delay == 0)
{ {
switch (p->mdepth) switch (p->mdepth)
{ {
@ -2050,15 +2140,12 @@ boolean M_CharacterSelectHandler(INT32 choice)
{ {
p->mdepth = CSSTEP_COLORS; p->mdepth = CSSTEP_COLORS;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
p->delay = MENUDELAYTIME; M_SetMenuDelay(i);
} }
break; break;
} }
} }
if (p->mdepth < CSSTEP_ALTS)
p->clonenum = 0;
// Just makes it easier to access later // Just makes it easier to access later
p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum]; p->skin = setup_chargrid[p->gridx][p->gridy].skinlist[p->clonenum];