diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index d2594bae8..cf63cef3f 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -4,6 +4,7 @@ bool System_WantGuiCapture(); // During playing this tells us whether the game m #include <stdint.h> #include "vectors.h" +#include "engineerrors.h" struct GameStats { @@ -84,6 +85,7 @@ struct GameInterface virtual void SetAmbience(bool on) {} virtual FString GetCoordString() { return "'stat coord' not implemented"; } virtual bool CheatAllowed(bool printmsg) { return true; } + virtual void ExitFromMenu() { throw CExitEvent(0); } }; diff --git a/source/core/menu/messagebox.cpp b/source/core/menu/messagebox.cpp index 44d7f3d1e..02090ec02 100644 --- a/source/core/menu/messagebox.cpp +++ b/source/core/menu/messagebox.cpp @@ -454,7 +454,7 @@ CCMD (menu_quit) DMenu *newmenu = CreateMessageBoxMenu(CurrentMenu, EndString, 0, 500, false, NAME_None, [](bool res) { - if (res) throw CExitEvent(0); + if (res) gi->ExitFromMenu(); }); M_ActivateMenu(newmenu); diff --git a/source/games/duke/src/2d_r.cpp b/source/games/duke/src/2d_r.cpp index e72f9608e..98641bb00 100644 --- a/source/games/duke/src/2d_r.cpp +++ b/source/games/duke/src/2d_r.cpp @@ -578,7 +578,7 @@ void dobonus_r(bool bonusonly, CompletionFunc completion) int levnum = clamp((currentLevel->levelNumber / 100) * 7 + (currentLevel->levelNumber % 100), 0, 13); char fn[20]; mysnprintf(fn, 20, "lvl%d.anm", levnum + 1); - static const int framespeed[] = { 20, 20, 7200 }; // wait for one minute on the final frame so that the video doesn't appear before the user notices. + static const int framespeed[] = { 20, 20, 7200 }; // wait for one minute on the final frame so that the video doesn't stop before the user notices. jobs[job++] = { PlayVideo(fn, nullptr, framespeed) }; if (ud.eog && currentLevel->levelNumber > 100) { diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 8c198fcb6..20ac92728 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -63,6 +63,7 @@ struct GameInterface : ::GameInterface void QuitToTitle() override; FString GetCoordString() override; bool CheatAllowed(bool printmsg) override; + void ExitFromMenu() override; }; struct Dispatcher diff --git a/source/games/duke/src/funct.h b/source/games/duke/src/funct.h index 5802b1979..92bb46e52 100644 --- a/source/games/duke/src/funct.h +++ b/source/games/duke/src/funct.h @@ -208,7 +208,7 @@ void drawstatusbar_d(int snum); void drawstatusbar_r(int snum); void drawoverheadmap(int cposx, int cposy, int czoom, int cang); void cameratext(int i); -void dobonus(int bonusonly); +void dobonus(int bonusonly, CompletionFunc completion); void dobonus_d(bool bonusonly, CompletionFunc completion); void dobonus_r(bool bonusonly, CompletionFunc completion); diff --git a/source/games/duke/src/game_misc.cpp b/source/games/duke/src/game_misc.cpp index a78e3a942..6ecec0474 100644 --- a/source/games/duke/src/game_misc.cpp +++ b/source/games/duke/src/game_misc.cpp @@ -109,22 +109,41 @@ void setmapfog(int fogtype) // //--------------------------------------------------------------------------- -void gameexitfrommenu() +static void runbonus(CompletionFunc completion) { // MP scoreboard if (playerswhenstarted > 1 && ps[myconnectindex].gm & MODE_GAME && !ud.coop) { - dobonus(1); + dobonus(1, completion); } + else if (completion) completion(false); +} +static void runtwoscreens(CompletionFunc completion) +{ // shareware and TEN screens if (!VOLUMEALL && !isRR()) - showtwoscreens([](bool) {}); + showtwoscreens(completion); + else if (completion) completion(false); +} +static void endthegame(bool) +{ endoomName = isRR() ? "redneck.bin" : VOLUMEALL ? "duke3d.bin" : "dukesw.bin"; ST_Endoom(); } + +void gameexitfrommenu() +{ + runbonus([](bool aborted) { runtwoscreens(endthegame); }); +} + +void GameInterface::ExitFromMenu() +{ + gameexitfrommenu(); +} + //--------------------------------------------------------------------------- // // This now redirects the messagew to the console's notification display @@ -704,11 +723,11 @@ void cameratext(int i) // //--------------------------------------------------------------------------- -void dobonus(int bonusonly) +void dobonus(int bonusonly, CompletionFunc completion) { - if (isRRRA()); - else if (isRR()) dobonus_r(bonusonly, nullptr); - else dobonus_d(bonusonly, nullptr); + if (isRRRA()) { if (completion) completion(false); } + else if (isRR()) dobonus_r(bonusonly, completion); + else dobonus_d(bonusonly, completion); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/input.cpp b/source/games/duke/src/input.cpp index 30e4f9a38..8b04d6f4e 100644 --- a/source/games/duke/src/input.cpp +++ b/source/games/duke/src/input.cpp @@ -893,12 +893,12 @@ static void processMovement(player_struct *p, input_t &input, ControlInfo &info, if (buttonMap.ButtonDown(gamefunc_Turn_Left)) { turnheldtime += tics; - input.q16avel -= fix16_from_dbl(2 * scaleFactor * (turnheldtime >= TURBOTURNTIME) ? turnamount : PREAMBLETURN); + input.q16avel -= fix16_from_dbl(2 * scaleFactor * (turnheldtime >= TURBOTURNTIME ? turnamount : PREAMBLETURN)); } else if (buttonMap.ButtonDown(gamefunc_Turn_Right)) { turnheldtime += tics; - input.q16avel += fix16_from_dbl(2 * scaleFactor * (turnheldtime >= TURBOTURNTIME) ? turnamount : PREAMBLETURN); + input.q16avel += fix16_from_dbl(2 * scaleFactor * (turnheldtime >= TURBOTURNTIME ? turnamount : PREAMBLETURN)); } else { @@ -1202,7 +1202,7 @@ static void FinalizeInput(int playerNum, input_t& input, bool vehicle) loc.q16avel += input.q16avel; if (!synchronized_input) { - p->q16ang = (p->q16ang + input.q16avel) & 0x7FFFFFF; + p->q16ang = (p->q16ang + input.q16avel * 2) & 0x7FFFFFF; // Why * 2 now? if (input.q16avel) p->one_eighty_count = 0; diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp index a8cfdb79a..a96a4d277 100644 --- a/source/games/duke/src/premap.cpp +++ b/source/games/duke/src/premap.cpp @@ -1093,7 +1093,7 @@ int exitlevel(void) if (ps[myconnectindex].gm & MODE_EOL) { ready2send = 0; - dobonus(0); + dobonus(0, nullptr); // Clear potentially loaded per-map ART only after the bonus screens. artClearMapArt();