SOC menus, part 1

This commit is contained in:
GenericHeroGuy 2025-03-15 04:03:44 +01:00
parent a23197cf8d
commit 0e30c0c5eb
6 changed files with 332 additions and 7 deletions

View file

@ -197,6 +197,21 @@ static inline int lib_freeslot(lua_State *L)
CONS_Alert(CONS_WARNING, "Ran out of free PRECIP slots!\n");
}
}
else if (fastcmp(type, "MN"))
{
menutype_t i;
for (i = 0; i < NUMMENUFREESLOTS; i++)
if (!FREE_MENUS[i]) {
CONS_Printf("Menu MN_%s allocated.\n",word);
FREE_MENUS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MENUS[i],word);
lua_pushinteger(L, MN_FIRSTFREESLOT + i);
r++;
break;
}
if (i == NUMMENUFREESLOTS)
CONS_Alert(CONS_WARNING, "Ran out of free menu slots!\n");
}
Z_Free(s);
lua_remove(L, 1);
continue;
@ -633,7 +648,15 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
}
else if (fastncmp("MN_",word,3)) {
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
for (i = 0; i < NUMMENUFREESLOTS; i++) {
if (!FREE_MENUS[i])
break;
if (fastcmp(p, FREE_MENUS[i])) {
CacheAndPushConstant(L, word, MN_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MN_FIRSTFREESLOT; i++)
if (fastcmp(p, MENUTYPES_LIST[i])) {
CacheAndPushConstant(L, word, i);
return 1;

View file

@ -534,6 +534,16 @@ void readfreeslots(MYFILE *f)
} else
deh_warning("Ran out of free PRECIP slots!\n");
}
else if (fastcmp(type, "MN"))
{
for (i = 0; i < NUMMENUFREESLOTS; i++)
if (!FREE_MENUS[i]) {
CONS_Printf("Menu MN_%s allocated.\n",word);
FREE_MENUS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MENUS[i],word);
break;
}
}
else
deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word);
}
@ -2135,17 +2145,21 @@ void readtextprompt(MYFILE *f, INT32 num)
Z_Free(s);
}
void readmenu(MYFILE *f, INT32 num)
static void readmenuitem(MYFILE *f, menu_t *menudef, char *itemname)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word = s;
char *word2;
char *tmp;
INT32 value;
do
{
if (myfgets(s, MAXLINELEN, f))
menuitem_t *menuitem = menudef->menuitems + menudef->numitems;
(void)itemname; // menuitem->itemname = Z_StrDup(itemname);
boolean actionset = false;
boolean textset = false;
// taking quite possibly the only opportunity i'll ever get
// to avoid three tabs of indentation...
do if (myfgets(s, MAXLINELEN, f))
{
if (s[0] == '\n')
break;
@ -2169,12 +2183,188 @@ void readmenu(MYFILE *f, INT32 num)
break;
strupr(word);
// Now get the part after
word2 = tmp += 2;
//strupr(word2);
if (fastcmp(word, "PATCH"))
{
menuitem->patch = Z_StrDup(word2);
}
else if (fastncmp(word, "TEXT", 4))
{
UINT16 flags = IT_STRING;
if (fastcmp(word+4, "HEADER"))
flags = IT_HEADER;
else if (fastcmp(word+4, "SECRET"))
flags = IT_SECRET;
else if (word[4])
{
deh_warning("MenuItem %s: unknown word '%s'", "", word);
continue;
}
if (textset)
{
deh_warning("MenuItem %s: text already set!", "");
continue;
}
textset = true;
menuitem->status |= flags;
menuitem->text = Z_StrDup(word2);
}
else if (fastncmp(word, "CVAR", 4))
{
UINT16 flags = IT_CVAR;
if (fastcmp(word+4, "SLIDER"))
flags |= IT_CV_SLIDER;
else if (fastcmp(word+4, "STRING"))
flags |= IT_CV_STRING;
else if (fastcmp(word+4, "INTEGER"))
flags |= IT_CV_INTEGERSTEP;
else if (word[4])
{
deh_warning("MenuItem %s: unknown word '%s'", "", word);
continue;
}
if (actionset)
{
deh_warning("MenuItem %s: action already set!", "");
continue;
}
consvar_t *cvar = CV_FindVar(word2);
if (!cvar)
{
deh_warning("MenuItem %s: unable to find cvar '%s'", "", word2);
continue;
}
actionset = true;
menuitem->status |= flags;
menuitem->itemaction.cvar = cvar;
}
else if (fastcmp(word, "SUBMENU"))
{
if (actionset)
{
deh_warning("MenuItem %s: action already set!", "");
continue;
}
menutype_t mn = get_menutype(word2);
if (mn == MN_NONE)
{
deh_warning("MenuItem %s: unknown menu '%s'", "", word2);
continue;
}
actionset = true;
menuitem->status |= IT_SUBMENU;
menuitem->itemaction.submenu = menunum2menudef[mn];
}
else if (fastcmp(word, "CALL") || fastcmp(word, "KEYHANDLER"))
{
if (actionset)
{
deh_warning("MenuItem %s: action already set!", "");
continue;
}
void (*routine)(INT32 choice) = NULL; // TODO
if (!routine)
{
deh_warning("MenuItem %s: unknown call routine '%s'", "", word2);
continue;
}
actionset = true;
menuitem->status |= word[0] == 'C' ? IT_CALL : IT_KEYHANDLER;
menuitem->itemaction.routine = routine;
}
else if (fastcmp(word, "ALPHAKEY") || fastcmp(word, "Y"))
{
menuitem->alphaKey = atoi(word2);
}
else
deh_warning("MenuItem %s: unknown word '%s'", "", word);
}
while (!myfeof(f)); // finish when the line is empty
Z_Free(s);
}
void readmenu(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word = s;
char *word2;
char *tmp;
INT32 value;
boolean space = false;
menu_t *menudef = menunum2menudef[num];
if (menudef == NULL)
{
deh_warning("No def for menu %d, that is certainly strange...", num);
return;
}
//menuactive = false;
memset(menudef, 0, sizeof(menu_t));
menudef->menuid = num;
menudef->drawroutine = M_DrawGenericMenu;
do
{
if (myfgets(s, MAXLINELEN, f))
{
if (s[0] == '\n')
break;
// First remove trailing newline, if there is one
tmp = strchr(s, '\n');
if (tmp)
*tmp = '\0';
tmp = strchr(s, '#');
if (tmp)
*tmp = '\0';
if (s == tmp)
continue; // Skip comment lines, but don't break.
space = false;
// Get the part before the " = "
tmp = strchr(s, '=');
if (tmp)
*(tmp-1) = '\0';
else
{
space = true;
tmp = strchr(s, ' ');
if (tmp)
*tmp-- = '\0'; // decrement after, so word2 is correct
else
break;
}
strupr(word);
// Now get the part after
word2 = (tmp += 2);
strupr(word2);
value = atoi(word2); // used for numerical settings
if (space)
{
if (fastcmp(word, "MENUITEM"))
{
menudef->menuitems = Z_Realloc(menudef->menuitems, sizeof(menuitem_t)*(menudef->numitems+1), PU_STATIC, NULL);
readmenuitem(f, menudef, word2);
menudef->numitems++;
}
else
deh_warning("Menu %d: unknown word '%s'", num, word);
continue;
}
if (fastcmp(word, "BACKGROUNDNAME"))
{
strncpy(menupres[num].bgname, word2, 8);
@ -2315,6 +2505,45 @@ void readmenu(MYFILE *f, INT32 num)
menupres[num].exitwipe = get_number(word2);
titlechanged = true;
}
// MENUDEF STARTS HERE
else if (fastcmp(word, "MENUTITLEPIC") || fastcmp(word, "TITLEPIC"))
{
menudef->menutitlepic = Z_StrDup(word2);
}
else if (fastcmp(word, "PREVMENU"))
{
value = get_menutype(word2);
if (value == MN_NONE)
{
deh_warning("Menu %d: unknown previous menu '%s'", num, word2);
continue;
}
menudef->prevMenu = menunum2menudef[value];
}
else if (fastcmp(word, "DRAWROUTINE"))
{
{
deh_warning("Menu %d: unknown draw routine '%s'", num, word2);
continue;
}
}
else if (fastcmp(word, "X"))
{
menudef->x = value;
}
else if (fastcmp(word, "Y"))
{
menudef->y = value;
}
else if (fastcmp(word, "QUITROUTINE"))
{
{
deh_warning("Menu %d: unknown quit routine '%s'", num, word2);
continue;
}
}
else
deh_warning("Menu %d: unknown word '%s'", num, word);
}
} while (!myfeof(f)); // finish when the line is empty
@ -4061,7 +4290,13 @@ menutype_t get_menutype(const char *word)
return atoi(word);
if (fastncmp("MN_",word,3))
word += 3; // take off the MN_
for (i = 0; i < NUMMENUTYPES; i++)
for (i = 0; i < NUMMENUFREESLOTS; i++) {
if (!FREE_MENUS[i])
break;
if (fastcmp(word, FREE_MENUS[i]))
return MN_FIRSTFREESLOT+i;
}
for (i = 0; i < MN_FIRSTFREESLOT; i++)
if (fastcmp(word, MENUTYPES_LIST[i]))
return i;
deh_warning("Couldn't find menutype named 'MN_%s'",word);

View file

@ -33,6 +33,7 @@
char *FREE_STATES[NUMSTATEFREESLOTS];
char *FREE_MOBJS[NUMMOBJFREESLOTS];
char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
char *FREE_MENUS[NUMMENUFREESLOTS];
UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
struct flickytypes_s FLICKYTYPES[] = {
@ -615,6 +616,8 @@ const char *const MENUTYPES_LIST[] = {
"SP_NIGHTS_REPLAY",
"SP_NIGHTS_GHOST",
"SP_MARATHON",
// Multiplayer
"MP_MAIN",
"MP_SPLITSCREEN", // SplitServer
@ -681,6 +684,17 @@ const char *const MENUTYPES_LIST[] = {
// "MAPAUSE",
// "HELP",
// SRB2Kart
"OP_HUD",
"OP_CHAT",
"OP_GAME",
"OP_BLANKARTGAME",
"OP_ADVANCEDSERVER",
"OP_CAMERA",
"OP_P3CAMERA",
"OP_P4CAMERA",
"MISC_REPLAY",
"SPECIAL"
};

View file

@ -16,6 +16,7 @@
#include "doomdef.h" // Constants
#include "d_think.h" // actionf_t
#include "info.h" // Mobj, state, sprite, etc constants
#include "m_menu.h" // NUMMENUFREESLOTS
#include "lua_script.h"
#ifdef __cplusplus
@ -27,6 +28,7 @@ extern "C" {
extern char *FREE_STATES[NUMSTATEFREESLOTS];
extern char *FREE_MOBJS[NUMMOBJFREESLOTS];
extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS];
extern char *FREE_MENUS[NUMMENUFREESLOTS];
extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway.
#define initfreeslots() {\

View file

@ -203,6 +203,9 @@ static void M_HandleServerPage(INT32 choice);
void M_SetWaitingMode(int mode);
int M_GetWaitingMode(void);
// a single freeslot menu for testing
menu_t FreeslotTest;
// the haxor message menu
menu_t MessageDef;
@ -359,7 +362,6 @@ static void M_PlaybackQuit(INT32 choice);
static UINT8 playback_enterheld = 0; // horrid hack to prevent holding the button from being extremely fucked
// Drawing functions
static void M_DrawGenericMenu(void);
static void M_DrawGenericBackgroundMenu(void);
static void M_DrawCenteredMenu(void);
static void M_DrawAddons(void);
@ -410,6 +412,33 @@ static void Dummymenuplayer_OnChange(void);
//static void Dummymares_OnChange(void);
static void Dummystaff_OnChange(void);
// temporary measure until menu_t and menupres_t are merged (hopefully)
menu_t *menunum2menudef[NUMMENUTYPES] = {
[MN_OP_CAMERA] = &OP_CamOptionsDef,
[MN_OP_P1CAMERA] = &OP_Player1CamOptionsDef,
[MN_OP_P2CAMERA] = &OP_Player2CamOptionsDef,
[MN_OP_P3CAMERA] = &OP_Player3CamOptionsDef,
[MN_OP_P4CAMERA] = &OP_Player4CamOptionsDef,
[MN_OP_MAIN] = &OP_MainDef,
[MN_OP_CHANGECONTROLS] = &OP_ControlsDef,
[MN_OP_VIDEO] = &OP_VideoOptionsDef,
[MN_OP_OPENGL] = &OP_OpenGLOptionsDef,
[MN_OP_SOUND] = &OP_SoundOptionsDef,
[MN_OP_CHAT] = &OP_ChatOptionsDef,
[MN_OP_HUD] = &OP_HUDOptionsDef,
[MN_OP_GAME] = &OP_GameOptionsDef,
[MN_OP_BLANKARTGAME] = &OP_BlanKartGameOptionsDef,
[MN_OP_SERVER] = &OP_ServerOptionsDef,
[MN_OP_ADVANCEDSERVER] = &OP_AdvServerOptionsDef,
[MN_OP_MONITORTOGGLE] = &OP_MonitorToggleDef,
[MN_OP_DATA] = &OP_DataOptionsDef,
[MN_OP_ERASEDATA] = &OP_EraseDataDef,
[MN_MISC_REPLAY] = &MISC_ReplayOptionsDef,
[MN_FIRSTFREESLOT] = &FreeslotTest,
};
// ==========================================================================
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ==========================================================================
@ -3003,6 +3032,9 @@ boolean M_Responder(event_t *ev)
break;
case IT_SUBMENU:
currentMenu->lastOn = itemOn;
if ((menu_t *)(currentMenu->menuitems[itemOn].itemaction.submenu)->menuitems == NULL)
CONS_Alert(CONS_WARNING, "Submenu is empty!\n");
else
M_SetupNextMenu((menu_t *)currentMenu->menuitems[itemOn].itemaction.submenu);
break;
}
@ -3919,7 +3951,7 @@ static void M_DrawMenuTitle(void)
}
}
static void M_DrawGenericMenu(void)
void M_DrawGenericMenu(void)
{
INT32 x, y, w, i, cursory = 0;

View file

@ -138,13 +138,30 @@ typedef enum
// MN_MAPAUSE,
// MN_HELP,
// SRB2Kart
MN_OP_HUD,
MN_OP_CHAT,
MN_OP_GAME,
MN_OP_BLANKARTGAME,
MN_OP_ADVANCEDSERVER,
MN_OP_CAMERA,
MN_OP_P3CAMERA,
MN_OP_P4CAMERA,
MN_MISC_REPLAY,
MN_SPECIAL,
MN_FIRSTFREESLOT,
MN_LASTFREESLOT,
NUMMENUTYPES,
} menutype_t; // up to 63; MN_SPECIAL = 53
} menutype_t; // up to 63
#define NUMMENUFREESLOTS (NUMMENUTYPES - MN_FIRSTFREESLOT)
#define MTREE2(a,b) (a | (b<<MENUBITS))
#define MTREE3(a,b,c) MTREE2(a, MTREE2(b,c))
#define MTREE4(a,b,c,d) MTREE2(a, MTREE3(b,c,d))
extern menu_t *menunum2menudef[NUMMENUTYPES];
typedef struct
{
char bgname[8]; // name for background gfx lump; lays over titlemap if this is set
@ -355,6 +372,8 @@ struct menu_t
void M_SetupNextMenu(menu_t *menudef);
void M_ClearMenus(boolean callexitmenufunc);
void M_DrawGenericMenu(void);
// Maybe this goes here????? Who knows.
boolean M_MouseNeeded(void);