From 67b7d2408b2536c9012ab002eed772a3378def21 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Fri, 9 Aug 2019 08:21:19 +0000 Subject: [PATCH] newgamechoices git-svn-id: https://svn.eduke32.com/eduke32@7930 1a8010ca-5511-0410-912e-c29ae57300e0 # Conflicts: # source/build/src/defs.cpp --- source/build/src/defs.cpp | 12 +- source/duke3d/src/events_defs.h | 1 + source/duke3d/src/game.cpp | 143 ++++++++++++++++++++++ source/duke3d/src/gamedef.cpp | 1 + source/duke3d/src/gamedef.h | 2 + source/duke3d/src/gamestructures.cpp | 12 ++ source/duke3d/src/menus.cpp | 174 ++++++++++++++++++++++++++- source/duke3d/src/menus.h | 29 +++++ 8 files changed, 370 insertions(+), 4 deletions(-) diff --git a/source/build/src/defs.cpp b/source/build/src/defs.cpp index 85170ed0c..42f01fda7 100644 --- a/source/build/src/defs.cpp +++ b/source/build/src/defs.cpp @@ -123,6 +123,7 @@ enum scripttoken_t T_SHADEFACTOR, T_RFFDEFINEID, T_IFCRC, + T_NEWGAMECHOICES, }; static int32_t lastmodelid = -1, lastvoxid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0; @@ -405,7 +406,7 @@ static int32_t defsparser(scriptfile *script) { "undefpalookuprange", T_UNDEFPALOOKUPRANGE }, { "undefblendtablerange", T_UNDEFBLENDTABLERANGE }, { "shadefactor", T_SHADEFACTOR }, - + { "newgamechoices", T_NEWGAMECHOICES }, { "rffdefineid", T_RFFDEFINEID }, // dummy }; @@ -3645,6 +3646,15 @@ static int32_t defsparser(scriptfile *script) paletteloaded &= ~PALETTE_TRANSLUC; } break; + case T_NEWGAMECHOICES: // stub + { + char *blockend; + if (scriptfile_getbraces(script,&blockend)) + break; + script->textptr = blockend; + break; + } + case T_RFFDEFINEID: { char *dummy; diff --git a/source/duke3d/src/events_defs.h b/source/duke3d/src/events_defs.h index 636b69d81..a1de4328b 100644 --- a/source/duke3d/src/events_defs.h +++ b/source/duke3d/src/events_defs.h @@ -159,6 +159,7 @@ enum GameEvent_t { EVENT_DISPLAYROOMSCAMERATILE, EVENT_RESETGOTPICS, EVENT_VALIDATESTART, + EVENT_NEWGAMECUSTOM, #ifdef LUNATIC EVENT_ANIMATEALLSPRITES, #endif diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 16cf73fc1..6d8f6ec1c 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -187,6 +187,11 @@ enum gametokens T_FORCEFILTER, T_FORCENOFILTER, T_TEXTUREFILTER, + T_NEWGAMECHOICES, + T_CHOICE, + T_NAME, + T_LOCKED, + T_HIDDEN, }; void G_HandleSpecialKeys(void) @@ -5291,6 +5296,7 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) { "animsounds", T_ANIMSOUNDS }, { "renamefile", T_RENAMEFILE }, { "globalgameflags", T_GLOBALGAMEFLAGS }, + { "newgamechoices", T_NEWGAMECHOICES }, }; static const tokenlist soundTokens[] = @@ -5315,6 +5321,24 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) { "texturefilter", T_TEXTUREFILTER }, }; + static const tokenlist newGameTokens[] = + { + { "choice", T_CHOICE }, + }; + static const tokenlist newGameChoiceTokens[] = + { + { "name", T_NAME }, + { "locked", T_LOCKED }, + { "hidden", T_HIDDEN }, + { "choice", T_CHOICE }, + }; + static const tokenlist newGameSubchoiceTokens[] = + { + { "name", T_NAME }, + { "locked", T_LOCKED }, + { "hidden", T_HIDDEN }, + }; + do { token = getatoken(pScript, tokens, ARRAY_SIZE(tokens)); @@ -5557,6 +5581,125 @@ static int parsedefinitions_game(scriptfile *pScript, int firstPass) } break; case T_GLOBALGAMEFLAGS: scriptfile_getnumber(pScript, &duke3d_globalflags); break; + case T_NEWGAMECHOICES: + { + char * newGameChoicesEnd; + if (scriptfile_getbraces(pScript,&newGameChoicesEnd)) + break; + if (firstPass) + { + pScript->textptr = newGameChoicesEnd; + break; + } + + while (pScript->textptr < newGameChoicesEnd) + { + switch (getatoken(pScript, newGameTokens, ARRAY_SIZE(newGameTokens))) + { + case T_CHOICE: + { + char * choicePtr = pScript->ltextptr; + char * choiceEnd; + int32_t choiceID; + if (scriptfile_getsymbol(pScript,&choiceID)) + break; + if (scriptfile_getbraces(pScript,&choiceEnd)) + break; + + if ((unsigned)choiceID >= MAXMENUGAMEPLAYENTRIES) + { + initprintf("Error: Maximum choices exceeded near line %s:%d\n", + pScript->filename, scriptfile_getlinum(pScript, choicePtr)); + pScript->textptr = choiceEnd; + } + + MenuGameplayStemEntry & stem = g_MenuGameplayEntries[choiceID]; + stem = MenuGameplayStemEntry{}; + MenuGameplayEntry & entry = stem.entry; + + while (pScript->textptr < choiceEnd) + { + switch (getatoken(pScript, newGameChoiceTokens, ARRAY_SIZE(newGameChoiceTokens))) + { + case T_CHOICE: + { + char * subChoicePtr = pScript->ltextptr; + char * subChoiceEnd; + int32_t subChoiceID; + if (scriptfile_getsymbol(pScript,&subChoiceID)) + break; + if (scriptfile_getbraces(pScript,&subChoiceEnd)) + break; + + if ((unsigned)subChoiceID >= MAXMENUGAMEPLAYENTRIES) + { + initprintf("Error: Maximum subchoices exceeded near line %s:%d\n", + pScript->filename, scriptfile_getlinum(pScript, subChoicePtr)); + pScript->textptr = subChoiceEnd; + } + + MenuGameplayEntry & subentry = stem.subentries[subChoiceID]; + subentry = MenuGameplayEntry{}; + + while (pScript->textptr < subChoiceEnd) + { + switch (getatoken(pScript, newGameSubchoiceTokens, ARRAY_SIZE(newGameSubchoiceTokens))) + { + case T_NAME: + { + char *name = NULL; + if (scriptfile_getstring(pScript, &name)) + break; + + memset(subentry.name, 0, ARRAY_SIZE(subentry.name)); + strncpy(subentry.name, name, ARRAY_SIZE(subentry.name)-1); + break; + } + case T_LOCKED: + { + subentry.flags |= MGE_Locked; + break; + } + case T_HIDDEN: + { + subentry.flags |= MGE_Hidden; + break; + } + } + } + + break; + } + case T_NAME: + { + char *name = NULL; + if (scriptfile_getstring(pScript, &name)) + break; + + memset(entry.name, 0, ARRAY_SIZE(entry.name)); + strncpy(entry.name, name, ARRAY_SIZE(entry.name)-1); + break; + } + case T_LOCKED: + { + entry.flags |= MGE_Locked; + break; + } + case T_HIDDEN: + { + entry.flags |= MGE_Hidden; + break; + } + } + } + + break; + } + } + } + + break; + } case T_EOF: return 0; default: break; } diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index f007a717c..c6762d65c 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -990,6 +990,7 @@ const char *EventNames[MAXEVENTS] = "EVENT_DISPLAYROOMSCAMERATILE", "EVENT_RESETGOTPICS", "EVENT_VALIDATESTART", + "EVENT_NEWGAMECUSTOM", #ifdef LUNATIC "EVENT_ANIMATEALLSPRITES", #endif diff --git a/source/duke3d/src/gamedef.h b/source/duke3d/src/gamedef.h index 7428e447f..01c531df9 100644 --- a/source/duke3d/src/gamedef.h +++ b/source/duke3d/src/gamedef.h @@ -635,6 +635,8 @@ enum UserdefsLabel_t USERDEFS_DRAW_Y, USERDEFS_DRAW_YXASPECT, USERDEFS_FOV, + USERDEFS_NEWGAMECUSTOMOPEN, + USERDEFS_NEWGAMECUSTOMSUBOPEN, USERDEFS_END }; diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp index 4949bf91b..a1ce77ca6 100644 --- a/source/duke3d/src/gamestructures.cpp +++ b/source/duke3d/src/gamestructures.cpp @@ -1358,6 +1358,8 @@ const memberlabel_t UserdefsLabels[]= { "draw_y", USERDEFS_DRAW_Y, 0, 0, -1 }, { "draw_yxaspect", USERDEFS_DRAW_YXASPECT, 0, 0, -1 }, { "fov", USERDEFS_FOV, 0, 0, -1 }, + { "newgamecustomopen", USERDEFS_NEWGAMECUSTOMOPEN, 0, 0, -1 }, + { "newgamecustomsubopen", USERDEFS_NEWGAMECUSTOMSUBOPEN, LABEL_HASPARM2, MAXMENUGAMEPLAYENTRIES, -1 }, }; int32_t __fastcall VM_GetUserdef(int32_t labelNum, int const lParm2) @@ -1750,6 +1752,16 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_DRAW_Y: rotatesprite_y_offset = iSet; break; case USERDEFS_DRAW_YXASPECT: rotatesprite_yxaspect = iSet; break; case USERDEFS_FOV: ud.fov = iSet; break; + case USERDEFS_NEWGAMECUSTOMOPEN: + for (unsigned int b = 0; b < MAXMENUGAMEPLAYENTRIES; ++b) + if (iSet & (1u<= MAXMENUGAMEPLAYENTRIES) + return; + + MenuGameplayStemEntry const & stem = g_MenuGameplayEntries[e]; + MenuGameplayEntry const & entry = stem.entry; + if (!entry.isValid()) + return; + + M_NEWGAMECUSTOMSUB.title = entry.name; + + int s = 0; + for (MenuGameplayEntry const & subentry : stem.subentries) + { + if (!subentry.isValid()) + break; + + MEL_NEWGAMECUSTOMSUB[s] = &ME_NEWGAMECUSTOMSUBENTRIES[e][s]; + + ++s; + } + M_NEWGAMECUSTOMSUB.numEntries = s; + MMF_Top_NewGameCustomSub.pos.y = (58 + (3-s)*6)<<16; +} + /* This function prepares data after ART and CON have been processed. It also initializes some data in loops rather than statically at compile time. @@ -1639,6 +1702,60 @@ void Menu_Init(void) MEO_EPISODE.linkID = MENU_NULL; M_EPISODE.currentEntry = ud.default_volume; + // prepare new game custom :O + if (g_MenuGameplayEntries[0].entry.isValid()) + { + MEO_MAIN_NEWGAME.linkID = M_NEWVERIFY.linkID = MENU_NEWGAMECUSTOM; + + int e = 0; + for (MenuGameplayStemEntry const & stem : g_MenuGameplayEntries) + { + MenuGameplayEntry const & entry = stem.entry; + if (!entry.isValid()) + break; + + MenuEntry_t & e_me = ME_NEWGAMECUSTOMENTRIES[e]; + e_me = ME_EPISODE_TEMPLATE; + MenuLink_t & e_meo = MEO_NEWGAMECUSTOM[e]; + e_meo = MEO_NEWGAMECUSTOM_TEMPLATE; + e_me.entry = &e_meo; + + e_me.name = entry.name; + if (entry.flags & MGE_Locked) + e_me.flags |= MEF_Disabled; + if (entry.flags & MGE_Hidden) + e_me.flags |= MEF_Hidden; + + int s = 0; + for (MenuGameplayEntry const & subentry : stem.subentries) + { + if (!subentry.isValid()) + break; + + MenuEntry_t & s_me = ME_NEWGAMECUSTOMSUBENTRIES[e][s]; + s_me = ME_EPISODE_TEMPLATE; + MenuLink_t & s_meo = MEO_NEWGAMECUSTOMSUB[e][s]; + s_meo = MEO_NEWGAMECUSTOMSUB_TEMPLATE; + s_me.entry = &s_meo; + + s_me.name = subentry.name; + if (subentry.flags & MGE_Locked) + s_me.flags |= MEF_Disabled; + if (subentry.flags & MGE_Hidden) + s_me.flags |= MEF_Hidden; + + ++s; + } + + if (s == 0) + e_meo.linkID = MENU_SKILL; + + ++e; + } + + Menu_PopulateNewGameCustom(); + } + // prepare skills k = -1; for (i = 0; i < g_skillCnt && g_skillNames[i][0]; ++i) @@ -2951,6 +3068,17 @@ static void Menu_EntryLinkActivate(MenuEntry_t *entry) } break; + case MENU_NEWGAMECUSTOM: + ud.returnvar[0] = -1; + VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); + break; + + case MENU_NEWGAMECUSTOMSUB: + ud.returnvar[0] = M_NEWGAMECUSTOMSUB.currentEntry; + ud.returnvar[1] = -1; + VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, M_NEWGAMECUSTOM.currentEntry); + break; + case MENU_SKILL: { int32_t skillsound = PISTOL_BODYHIT; @@ -3987,6 +4115,10 @@ static void Menu_AboutToStartDisplaying(Menu_t * m) ME_MAIN_LOADGAME.name = s_LoadGame; break; + case MENU_NEWGAMECUSTOMSUB: + Menu_PopulateNewGameCustomSub(M_NEWGAMECUSTOM.currentEntry); + break; + case MENU_LOAD: if (FURY) M_LOAD.title = (g_player[myconnectindex].ps->gm & MODE_GAME) ? s_LoadGame : s_Continue; @@ -6828,6 +6960,12 @@ void M_DisplayMenus(void) { ud.returnvar[0] = origin.x; ud.returnvar[1] = origin.y; + if (m_parentMenu->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_parentMenu->object)->currentEntry; + if (m_parentMenu->menuID == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENU, g_player[screenpeek].ps->i, screenpeek, m_parentMenu->menuID); origin.x = ud.returnvar[0]; origin.y = ud.returnvar[1]; @@ -6843,6 +6981,12 @@ void M_DisplayMenus(void) ud.returnvar[0] = previousOrigin.x; ud.returnvar[1] = previousOrigin.y; + if (m_animation.previous->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_animation.previous->object)->currentEntry; + if (m_animation.previous->menuID == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENU, g_player[screenpeek].ps->i, screenpeek, m_animation.previous->menuID); previousOrigin.x = ud.returnvar[0]; previousOrigin.y = ud.returnvar[1]; @@ -6850,6 +6994,12 @@ void M_DisplayMenus(void) ud.returnvar[0] = origin.x; ud.returnvar[1] = origin.y; + if (m_currentMenu->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_currentMenu->object)->currentEntry; + if (g_currentMenu == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYMENU, g_player[screenpeek].ps->i, screenpeek, g_currentMenu); origin.x = ud.returnvar[0]; origin.y = ud.returnvar[1]; @@ -6881,6 +7031,12 @@ void M_DisplayMenus(void) { ud.returnvar[0] = origin.x; ud.returnvar[1] = origin.y; + if (m_parentMenu->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_parentMenu->object)->currentEntry; + if (m_parentMenu->menuID == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENUREST, g_player[screenpeek].ps->i, screenpeek, m_parentMenu->menuID); } @@ -6888,11 +7044,23 @@ void M_DisplayMenus(void) { ud.returnvar[0] = previousOrigin.x; ud.returnvar[1] = previousOrigin.y; + if (m_animation.previous->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_animation.previous->object)->currentEntry; + if (m_animation.previous->menuID == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYINACTIVEMENUREST, g_player[screenpeek].ps->i, screenpeek, m_animation.previous->menuID); } ud.returnvar[0] = origin.x; ud.returnvar[1] = origin.y; + if (m_currentMenu->type == Menu) + { + ud.returnvar[2] = ((MenuMenu_t *)m_currentMenu->object)->currentEntry; + if (g_currentMenu == MENU_NEWGAMECUSTOMSUB) + ud.returnvar[3] = M_NEWGAMECUSTOM.currentEntry; + } VM_OnEventWithReturn(EVENT_DISPLAYMENUREST, g_player[screenpeek].ps->i, screenpeek, g_currentMenu); #if !defined EDUKE32_TOUCH_DEVICES diff --git a/source/duke3d/src/menus.h b/source/duke3d/src/menus.h index c29300795..fc9d812c2 100644 --- a/source/duke3d/src/menus.h +++ b/source/duke3d/src/menus.h @@ -44,6 +44,8 @@ enum MenuIndex_t { MENU_MAIN_INGAME = 50, MENU_EPISODE = 100, MENU_USERMAP = 101, + MENU_NEWGAMECUSTOM = 102, + MENU_NEWGAMECUSTOMSUB = 103, MENU_SKILL = 110, MENU_GAMESETUP = 200, MENU_OPTIONS = 202, @@ -490,6 +492,33 @@ extern int32_t m_mousewake_watchpoint, m_menuchange_watchpoint; # define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || m_mousewake_watchpoint || m_menuchange_watchpoint == 3) #endif +#define MAXMENUGAMEPLAYENTRIES 7 + +enum MenuGameplayEntryFlags +{ + MGE_Locked = 1u<<0u, + MGE_Hidden = 1u<<1u, +}; + +typedef struct MenuGameplayEntry +{ + char name[64]; + uint8_t flags; + + bool isValid() const { return name[0] != '\0'; } +} MenuGameplayEntry; + +typedef struct MenuGameplayStemEntry +{ + MenuGameplayEntry entry; + MenuGameplayEntry subentries[MAXMENUGAMEPLAYENTRIES]; +} MenuGameplayStemEntry; + +extern MenuGameplayStemEntry g_MenuGameplayEntries[MAXMENUGAMEPLAYENTRIES]; + +extern MenuEntry_t ME_NEWGAMECUSTOMENTRIES[MAXMENUGAMEPLAYENTRIES]; +extern MenuEntry_t ME_NEWGAMECUSTOMSUBENTRIES[MAXMENUGAMEPLAYENTRIES][MAXMENUGAMEPLAYENTRIES]; + #ifdef __cplusplus } #endif