diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index 776b4e319..0761bb81a 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -99,6 +99,7 @@ struct GameInterface : ::GameInterface bool LoadGame(FSaveGameNode*) override; void DoPrintMessage(int prio, const char*) override; void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg); + void QuitToTitle() override; }; diff --git a/source/blood/src/d_menu.cpp b/source/blood/src/d_menu.cpp index 107c2a933..3444b1a06 100644 --- a/source/blood/src/d_menu.cpp +++ b/source/blood/src/d_menu.cpp @@ -284,13 +284,33 @@ void GameInterface::DrawCenteredTextScreen(const DVector2& origin, const char* t { if (text) { - int width; - viewGetFontInfo(0, text, &width, NULL); - int x = 160 - width / 2; - viewDrawText(0, text, x, 100, 0, 0, 0, false); + int width, height = 0; + viewGetFontInfo(0, "T", &width, &height); + + auto lines = FString(text).Split("\n"); + int y = 100 - (height * lines.Size() / 2); + for (auto& l : lines) + { + int lheight = 0; + viewGetFontInfo(0, l, &width, &lheight); + int x = 160 - width / 2; + viewDrawText(0, l, x, y, 0, 0, 0, false); + y += height; + } } } +void GameInterface::QuitToTitle() +{ + if (gGameOptions.nGameType == 0 || numplayers == 1) + { + gQuitGame = true; + gRestartGame = true; + } + else + gQuitRequest = 2; +} + END_BLD_NS //---------------------------------------------------------------------------- diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 5c39c6bab..f590174c4 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -237,6 +237,8 @@ struct GameInterface DoPrintMessage(prio, f); } virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {} + virtual void QuitToTitle() {} + }; extern GameInterface* gi; diff --git a/source/common/menu/menu.cpp b/source/common/menu/menu.cpp index 7163ccf0d..392289f1a 100644 --- a/source/common/menu/menu.cpp +++ b/source/common/menu/menu.cpp @@ -498,7 +498,7 @@ bool M_SetMenu(FName menu, int param, FName caller) case NAME_EndgameMenu: // This is no separate class - C_DoCommand("memnu_endgame"); + C_DoCommand("menu_endgame"); return true; } @@ -806,7 +806,7 @@ bool M_DoResponder (event_t *ev) bool M_Responder(event_t* ev) { - // delayed deletion, so that self-deleting menus don't crash if they are getting accesses after being closed. + // delayed deletion, so that self-deleting menus don't crash if they are getting accessed after being closed. auto res = M_DoResponder(ev); for (auto p : toDelete) delete p; toDelete.Clear(); @@ -827,6 +827,7 @@ void M_Ticker (void) { D_ProcessEvents(); // The main loop is blocked when the menu is open and cannot dispatch the events. if (transition.previous) transition.previous->Ticker(); + if (DMenu::CurrentMenu == nullptr) return; // In case one of the sub-screens has closed the menu. DMenu::CurrentMenu->Ticker(); for (int i = 0; i < NUM_MKEYS; ++i) diff --git a/source/common/menu/messagebox.cpp b/source/common/menu/messagebox.cpp index a40343405..5fe3c8248 100644 --- a/source/common/menu/messagebox.cpp +++ b/source/common/menu/messagebox.cpp @@ -407,17 +407,7 @@ CCMD (menu_endgame) { if (res) { - M_ClearMenus(); - /*/ - if (!netgame) - { - if (demorecording) - G_CheckDemoStatus(); - D_StartTitle(); - } - */ - - //gi->ReturnToTitle(); + gi->QuitToTitle(); } }); diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp index 0167ae340..7b8fc7fd2 100644 --- a/source/duke3d/src/d_menu.cpp +++ b/source/duke3d/src/d_menu.cpp @@ -754,6 +754,15 @@ bool GameInterface::DrawSpecialScreen(const DVector2 &origin, int tilenum) void GameInterface::DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) { if (bg) Menu_DrawBackground(origin); + else + { + // Only used for the confirmation screen. + int lines = 1; + for (int i = 0; text[i]; i++) if (text[i] == '\n') lines++; + int height = lines * Menu_GetFontHeight(NIT_SmallFont); + position -= height >> 17; + Menu_DrawCursorLeft(160 << 16, 130 << 16, 65536); + } mgametextcenter(int(origin.X * 65536), int((origin.Y + position) * 65536), text); } @@ -762,6 +771,13 @@ void GameInterface::DrawPlayerSprite(const DVector2& origin, bool onteam) rotatesprite_fs(int(origin.X * 65536) + (260<<16), int(origin.Y*65536) + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,onteam ? G_GetTeamPalette(playerteam) : G_CheckPlayerColor(playercolor),10); } +void GameInterface::QuitToTitle() +{ + g_player[myconnectindex].ps->gm = MODE_DEMO; + if (ud.recstat == 1) + G_CloseDemoWrite(); + artClearMapArt(); +} END_DUKE_NS //---------------------------------------------------------------------------- diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index baa49d0a6..21e187a22 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -170,6 +170,7 @@ struct GameInterface : ::GameInterface bool LoadGame(FSaveGameNode*) override; void DoPrintMessage(int prio, const char*) override; void DrawPlayerSprite(const DVector2& origin, bool onteam) override; + void QuitToTitle() override; }; diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 5e2cec747..990c1e04e 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -6165,6 +6165,11 @@ MAIN_LOOP_RESTART: do //main loop { gameHandleEvents(); + if (myplayer.gm == MODE_DEMO) + { + M_ClearMenus(); + goto MAIN_LOOP_RESTART; + } // only allow binds to function if the player is actually in a game (not in a menu, typing, et cetera) or demo inputState.SetBindsEnabled(!!(myplayer.gm & (MODE_GAME|MODE_DEMO))); diff --git a/source/duke3d/src/menus.cpp b/source/duke3d/src/menus.cpp index 3b2d343da..a57589d3c 100644 --- a/source/duke3d/src/menus.cpp +++ b/source/duke3d/src/menus.cpp @@ -74,19 +74,6 @@ void Menu_Init(void) - - -static void Menu_DrawVerifyPrompt(int32_t x, int32_t y, const char * text, int numlines = 1) -{ - mgametextcenter(x, y + (90<<16), text); -#ifndef EDUKE32_ANDROID_MENU - char const * inputs = CONTROL_LastSeenInput == LastSeenInput::Joystick - ? "Press (A) to accept, (B) to return." - : "(Y/N)"; - mgametextcenter(x, y + (90<<16) + MF_Bluefont.get_yline() * numlines, inputs); -#endif -} - static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) { int32_t i, j, l = 0; diff --git a/source/rr/src/d_menu.cpp b/source/rr/src/d_menu.cpp index 2bf67e573..8ca1d5998 100644 --- a/source/rr/src/d_menu.cpp +++ b/source/rr/src/d_menu.cpp @@ -469,6 +469,14 @@ void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text) void GameInterface::DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) { if (bg) Menu_DrawBackground(origin); + else + { + // Only used for the confirmation screen. + int lines = 1; + for (int i = 0; text[i]; i++) if (text[i] == '\n') lines++; + int height = lines * Menu_GetFontHeight(NIT_SmallFont); + position -= height >> 17; + } G_ScreenText(MF_Bluefont.tilenum, int((origin.X + 160) * 65536), int((origin.Y + position) * 65536), MF_Bluefont.zoom, 0, 0, text, 0, MF_Bluefont.pal, 2 | 8 | 16 | ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, MF_Bluefont.between.x, MF_Bluefont.between.y, MF_Bluefont.textflags | TEXT_XCENTER, 0, 0, xdim - 1, ydim - 1); @@ -483,6 +491,13 @@ void GameInterface::DrawPlayerSprite(const DVector2& origin, bool onteam) rotatesprite_fs(int(origin.X * 65536) + (260<<16), int(origin.Y * 65536) + ((24+(tilesiz[APLAYER].y>>1))<<16), 49152L,0,1441-((((4-((int32_t) totalclock>>4)))&3)*5),0,onteam ? G_GetTeamPalette(playerteam) : G_CheckPlayerColor(playercolor),10); } +void GameInterface::QuitToTitle() +{ + g_player[myconnectindex].ps->gm = MODE_DEMO; + if (ud.recstat == 1) + G_CloseDemoWrite(); + artClearMapArt(); +} END_RR_NS diff --git a/source/rr/src/duke3d.h b/source/rr/src/duke3d.h index 4430c56db..d64e30770 100644 --- a/source/rr/src/duke3d.h +++ b/source/rr/src/duke3d.h @@ -170,6 +170,7 @@ struct GameInterface : ::GameInterface bool LoadGame(FSaveGameNode*) override; void DoPrintMessage(int prio, const char* text) override; void DrawPlayerSprite(const DVector2& origin, bool onteam) override; + void QuitToTitle() override; }; END_RR_NS diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 33a5de7d5..633490c9b 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -7598,6 +7598,11 @@ MAIN_LOOP_RESTART: do //main loop { handleevents(); + if (g_player[myconnectindex].ps->gm == MODE_DEMO) + { + M_ClearMenus(); + goto MAIN_LOOP_RESTART; + } Net_GetPackets(); diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp index f7f4548b1..c7d0f553d 100644 --- a/source/sw/src/d_menu.cpp +++ b/source/sw/src/d_menu.cpp @@ -266,7 +266,7 @@ void GameInterface::DrawCenteredTextScreen(const DVector2& origin, const char* t for (auto& l : lines) { short lheight = 0; - MNU_MeasureString(text, &width, &lheight); + MNU_MeasureString(l, &width, &lheight); int x = 160 - width / 2; MNU_DrawString(x, y, l, 0, 0); y += height; diff --git a/wadsrc/static/demolition/menudef.txt b/wadsrc/static/demolition/menudef.txt index 4f00dda81..2fdea0f10 100644 --- a/wadsrc/static/demolition/menudef.txt +++ b/wadsrc/static/demolition/menudef.txt @@ -105,7 +105,7 @@ LISTMENU "IngameMenu" NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" NativeTextItem "$MNU_OPTIONS", "o", "OptionsMenu" NativeTextItem "$MNU_HELP", "h", "HelpMenu" - NativeTextItem "$MNU_ENDGAME", "e", "QuitToMenu" + NativeTextItem "$MNU_ENDGAME", "e", "EndgameMenu" NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" } ifgame(Blood) @@ -121,7 +121,7 @@ LISTMENU "IngameMenu" NativeTextItem "$MNU_LOADGAME", "l", "LoadGameMenu" NativeTextItem "$MNU_HELP", "h", "HelpMenu" NativeTextItem "$MNU_CREDITS", "c", "CreditsMenu" - NativeTextItem "$MNU_ENDGAME", "e", "QuitToMenu" + NativeTextItem "$MNU_ENDGAME", "e", "EndgameMenu" NativeTextItem "$MNU_QUITGAME", "q", "QuitMenu" } ifgame(ShadowWarrior)