static void BuildPlayerclassMenu() { bool success = false; // Build player class menu FMenuDescriptor **desc = MenuDescriptors.CheckKey(NAME_Playerclassmenu); if (desc != NULL) { if ((*desc)->mType == MDESC_ListMenu) { FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc); // add player display ld->mSelectedItem = ld->mItems.Size(); int posy = ld->mYpos; int topy = posy; // Get lowest y coordinate of any static item in the menu for(unsigned i = 0; i < ld->mItems.Size(); i++) { int y = ld->mItems[i]->GetY(); if (y < topy) topy = y; } // Count the number of items this menu will show int numclassitems = 0; for (unsigned i = 0; i < PlayerClasses.Size (); i++) { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != NULL) { numclassitems++; } } } // center the menu on the screen if the top space is larger than the bottom space int totalheight = posy + (numclassitems+1) * ld->mLinespacing - topy; if (numclassitems <= 1) { // create a dummy item that auto-chooses the default class. FListMenuItemText *it = new FListMenuItemText(0, 0, 0, 'p', "player", ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000); ld->mAutoselect = ld->mItems.Push(it); success = true; } else if (totalheight <= 190) { int newtop = (200 - totalheight + topy) / 2; int topdelta = newtop - topy; if (topdelta < 0) { for(unsigned i = 0; i < ld->mItems.Size(); i++) { ld->mItems[i]->OffsetPositionY(topdelta); } posy -= topdelta; } int n = 0; for (unsigned i = 0; i < PlayerClasses.Size (); i++) { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != NULL) { FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i); ld->mItems.Push(it); ld->mYpos += ld->mLinespacing; n++; } } } if (n > 1 && !gameinfo.norandomplayerclass) { FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', "$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1); ld->mItems.Push(it); } if (n == 0) { const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type); if (pname != NULL) { FListMenuItemText *it = new FListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0); ld->mItems.Push(it); } } success = true; } } } if (!success) { // Couldn't create the playerclass menu, either because there's too many episodes or some error occured // Create an option menu for class selection instead. FOptionMenuDescriptor *od = new FOptionMenuDescriptor; if (desc != NULL) delete *desc; MenuDescriptors[NAME_Playerclassmenu] = od; od->mType = MDESC_OptionsMenu; od->mMenuName = NAME_Playerclassmenu; od->mTitle = "$MNU_CHOOSECLASS"; od->mSelectedItem = 0; od->mScrollPos = 0; od->mClass = NULL; od->mPosition = -15; od->mScrollTop = 0; od->mIndent = 160; od->mDontDim = false; od->mNetgameMessage = "$NEWGAME"; for (unsigned i = 0; i < PlayerClasses.Size (); i++) { if (!(PlayerClasses[i].Flags & PCF_NOMENU)) { const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != NULL) { FOptionMenuItemSubmenu *it = new FOptionMenuItemSubmenu(pname, "Episodemenu", i); od->mItems.Push(it); } } } FOptionMenuItemSubmenu *it = new FOptionMenuItemSubmenu("Random", "Episodemenu", -1); od->mItems.Push(it); } }
void M_SetMenu(FName menu, int param) { // some menus need some special treatment switch (menu) { case NAME_Episodemenu: // sent from the player class menu GameStartupInfo.Skill = -1; GameStartupInfo.Episode = -1; GameStartupInfo.PlayerClass = param == -1000? NULL : param == -1? "Random" : GetPrintableDisplayName(PlayerClasses[param].Type); break; case NAME_Skillmenu: // sent from the episode menu if ((gameinfo.flags & GI_SHAREWARE) && param > 0) { // Only Doom and Heretic have multi-episode shareware versions. M_StartMessage(GStrings("SWSTRING"), 1); return; } GameStartupInfo.Episode = param; M_StartupSkillMenu(&GameStartupInfo); // needs player class name from class menu (later) break; case NAME_StartgameConfirm: { // sent from the skill menu for a skill that needs to be confirmed GameStartupInfo.Skill = param; const char *msg = AllSkills[param].MustConfirmText; if (*msg==0) msg = GStrings("NIGHTMARE"); M_StartMessage (msg, 0, NAME_StartgameConfirmed); return; } case NAME_Startgame: // sent either from skill menu or confirmation screen. Skill gets only set if sent from skill menu // Now we can finally start the game. Ugh... GameStartupInfo.Skill = param; case NAME_StartgameConfirmed: G_DeferedInitNew (&GameStartupInfo); if (gamestate == GS_FULLCONSOLE) { gamestate = GS_HIDECONSOLE; gameaction = ga_newgame; } M_ClearMenus (); return; case NAME_Savegamemenu: if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer) || gamestate != GS_LEVEL) { // cannot save outside the game. M_StartMessage (GStrings("SAVEDEAD"), 1); return; } } // End of special checks FMenuDescriptor **desc = MenuDescriptors.CheckKey(menu); if (desc != NULL) { if ((*desc)->mNetgameMessage.IsNotEmpty() && netgame) { M_StartMessage((*desc)->mNetgameMessage, 1); return; } if ((*desc)->mType == MDESC_ListMenu) { FListMenuDescriptor *ld = static_cast<FListMenuDescriptor*>(*desc); if (ld->mAutoselect >= 0 && ld->mAutoselect < (int)ld->mItems.Size()) { // recursively activate the autoselected item without ever creating this menu. ld->mItems[ld->mAutoselect]->Activate(); } else { const PClass *cls = ld->mClass == NULL? RUNTIME_CLASS(DListMenu) : ld->mClass; DListMenu *newmenu = (DListMenu *)cls->CreateNew(); newmenu->Init(DMenu::CurrentMenu, ld); M_ActivateMenu(newmenu); } } else if ((*desc)->mType == MDESC_OptionsMenu) { FOptionMenuDescriptor *ld = static_cast<FOptionMenuDescriptor*>(*desc); const PClass *cls = ld->mClass == NULL? RUNTIME_CLASS(DOptionMenu) : ld->mClass; DOptionMenu *newmenu = (DOptionMenu *)cls->CreateNew(); newmenu->Init(DMenu::CurrentMenu, ld); M_ActivateMenu(newmenu); } return; } else { const PClass *menuclass = PClass::FindClass(menu); if (menuclass != NULL) { if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu))) { DMenu *newmenu = (DMenu*)menuclass->CreateNew(); newmenu->mParentMenu = DMenu::CurrentMenu; M_ActivateMenu(newmenu); return; } } } Printf("Attempting to open menu of unknown type '%s'\n", menu.GetChars()); }