diff --git a/similar/main/menu.cpp b/similar/main/menu.cpp index a5eef7b3c..9fc132b25 100644 --- a/similar/main/menu.cpp +++ b/similar/main/menu.cpp @@ -1301,7 +1301,6 @@ void screen_resolution_menu::check_apply_preset_resolution() const void screen_resolution_menu::apply_custom_resolution() const { - char revert[32]; char *x; const char *errstr; const auto resolution_width = strtoul(crestext.data(), &x, 10); @@ -1313,8 +1312,22 @@ void screen_resolution_menu::apply_custom_resolution() const ) { cmode = Game_screen_mode; - snprintf(revert, sizeof(revert), "Revert to %ix%i", SM_W(cmode), SM_H(cmode)); - nm_messagebox_str(menu_title{TXT_WARNING}, revert, menu_subtitle{errstr}); + struct error_change_resolution : + std::array, + passive_messagebox + { + error_change_resolution(const char *errstr, screen_mode cmode) : + passive_messagebox(menu_title{TXT_WARNING}, menu_subtitle{errstr}, prepare_choice_text(*this, cmode), grd_curscreen->sc_canvas) + { + } + static const char *prepare_choice_text(std::array &b, screen_mode cmode) + { + auto r = b.data(); + std::snprintf(r, b.size(), "Revert to %ix%i", SM_W(cmode), SM_H(cmode)); + return r; + } + }; + run_blocking_newmenu(errstr, cmode); } else { @@ -1330,7 +1343,14 @@ void screen_resolution_menu::apply_custom_resolution() const ) { casp = cmode; - nm_messagebox_str(menu_title{TXT_WARNING}, "IGNORE ASPECT RATIO", menu_subtitle{errstr}); + struct error_invalid_aspect_ratio : passive_messagebox + { + error_invalid_aspect_ratio(const char *errstr) : + passive_messagebox(menu_title{TXT_WARNING}, menu_subtitle{errstr}, "IGNORE ASPECT RATIO", grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(errstr); } else { @@ -2109,7 +2129,16 @@ int graphics_config_menu::subfunction_handler(const d_event &event) case EVENT_WINDOW_CLOSE: #if DXX_USE_OGL if (CGameCfg.VSync != m[opt_gr_vsync].value || CGameCfg.Multisample != m[opt_gr_multisample].value) - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Setting VSync or 4x Multisample\nrequires restart on some systems."}); + { + struct warn_might_need_restart : passive_messagebox + { + warn_might_need_restart() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"On some systems, changing VSync or 4x Multisample\nrequires a restart."}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); + } for (const uint8_t i : xrange(3u)) if (m[i + opt_filter_none].value) diff --git a/similar/main/multi.cpp b/similar/main/multi.cpp index 4f7cb5c90..d78bb4826 100644 --- a/similar/main/multi.cpp +++ b/similar/main/multi.cpp @@ -1989,7 +1989,14 @@ void multi_disconnect_player(const playernum_t pnum) { if (Game_wind) window_set_visible(*Game_wind, 0); - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Host left the game!"}); + struct host_left_game : passive_messagebox + { + host_left_game() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"Host left the game!"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); if (Game_wind) window_set_visible(*Game_wind, 1); multi_quit_game = 1; diff --git a/similar/main/net_udp.cpp b/similar/main/net_udp.cpp index 5a4c4f118..3c4ebe1ae 100644 --- a/similar/main/net_udp.cpp +++ b/similar/main/net_udp.cpp @@ -4759,7 +4759,14 @@ int net_udp_do_join_game() if (Netgame.game_status == NETSTAT_ENDLEVEL) { - nm_messagebox_str(menu_title{TXT_SORRY}, nm_messagebox_tie(TXT_OK), menu_subtitle{TXT_NET_GAME_BETWEEN2}); + struct error_game_between_levels : passive_messagebox + { + error_game_between_levels() : + passive_messagebox(menu_title{TXT_SORRY}, menu_subtitle{TXT_NET_GAME_BETWEEN2}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } @@ -4776,7 +4783,22 @@ int net_udp_do_join_game() #endif if (const auto errstr = load_mission_by_name(mission_predicate, mission_name_type::guess)) { - nm_messagebox(menu_title{nullptr}, 1, TXT_OK, "%s\n\n%s", TXT_MISSION_NOT_FOUND, errstr); + struct error_mission_not_found : + std::array, + passive_messagebox + { + error_mission_not_found(const char *errstr) : + passive_messagebox(menu_title{nullptr}, menu_subtitle{prepare_subtitle(*this, errstr)}, TXT_OK, grd_curscreen->sc_canvas) + { + } + static const char *prepare_subtitle(std::array &b, const char *errstr) + { + auto r = b.data(); + std::snprintf(r, b.size(), "%s\n\n%s", TXT_MISSION_NOT_FOUND, errstr); + return r; + } + }; + run_blocking_newmenu(errstr); return 0; } } @@ -4786,7 +4808,14 @@ int net_udp_do_join_game() { if (Netgame.levelnum>8) { - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"This OEM version only supports\nthe first 8 levels!"}); + struct error_using_oem_data : passive_messagebox + { + error_using_oem_data() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"You are using OEM game data. You can only play the first 8 levels."}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } } @@ -4795,14 +4824,28 @@ int net_udp_do_join_game() { if (Netgame.levelnum > 4) { - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"This SHAREWARE version only supports\nthe first 4 levels!"}); + struct error_using_mac_shareware : passive_messagebox + { + error_using_mac_shareware() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"You are using Mac shareware data. You can only play the first 4 levels."}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } } if ( !HoardEquipped() && (Netgame.gamemode == NETGAME_HOARD || Netgame.gamemode == NETGAME_TEAM_HOARD) ) { - nm_messagebox_str(menu_title{TXT_SORRY}, nm_messagebox_tie(TXT_OK), menu_subtitle{"HOARD(.ham) not installed. You can't join."}); + struct error_hoard_not_available : passive_messagebox + { + error_hoard_not_available() : + passive_messagebox(menu_title{TXT_SORRY}, menu_subtitle{"That is a hoard game.\nYou do not have HOARD.HAM installed.\nYou cannot join."}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } @@ -4811,7 +4854,14 @@ int net_udp_do_join_game() if (net_udp_can_join_netgame(&Netgame) == join_netgame_status_code::game_in_disallowed_state) { - nm_messagebox_str(menu_title{TXT_SORRY}, nm_messagebox_tie(TXT_OK), menu_subtitle{Netgame.numplayers == Netgame.max_numplayers ? TXT_GAME_FULL : TXT_IN_PROGRESS}); + struct error_cannot_join_game : passive_messagebox + { + error_cannot_join_game() : + passive_messagebox(menu_title{TXT_SORRY}, menu_subtitle{Netgame.numplayers == Netgame.max_numplayers ? TXT_GAME_FULL : TXT_IN_PROGRESS}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } diff --git a/similar/main/newdemo.cpp b/similar/main/newdemo.cpp index 92f659102..5672b146b 100644 --- a/similar/main/newdemo.cpp +++ b/similar/main/newdemo.cpp @@ -3910,7 +3910,23 @@ void newdemo_start_recording() if (!outfile) { Newdemo_state = ND_STATE_NORMAL; - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Cannot open demo temp file"}); + struct error_writing_demo : + std::array, + passive_messagebox + { + error_writing_demo(const char *errstr) : + passive_messagebox(menu_title{nullptr}, menu_subtitle{prepare_subtitle(*this, errstr)}, "Cancel recording", grd_curscreen->sc_canvas) + { + } + static const char *prepare_subtitle(std::array &b, const char *errstr) + { + auto r = b.data(); + std::snprintf(r, b.size(), "Failed to open demo temporary file\n" DEMO_FILENAME "\n\n%s", errstr); + return r; + } + }; + const auto errstr = PHYSFS_getLastError(); + run_blocking_newmenu(errstr); } else newdemo_record_start_demo(); @@ -4136,7 +4152,14 @@ try_again: break; if (!isalnum(c) && c != '_' && c != '-' && c != '.') { - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_CONTINUE), menu_subtitle{TXT_DEMO_USE_LETTERS}); + struct error_invalid_demo_filename : passive_messagebox + { + error_invalid_demo_filename() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{TXT_DEMO_USE_LETTERS}, TXT_CONTINUE, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); goto try_again; } } diff --git a/similar/main/playsave.cpp b/similar/main/playsave.cpp index c8977cb61..89034918d 100644 --- a/similar/main/playsave.cpp +++ b/similar/main/playsave.cpp @@ -873,13 +873,27 @@ int read_player_file() #endif if (id!=SAVE_FILE_ID) { - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Invalid player file"}); + struct error_invalid_player_file_magic : passive_messagebox + { + error_invalid_player_file_magic() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{"Invalid player file"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return -1; } #if defined(DXX_BUILD_DESCENT_I) if (saved_game_version < COMPATIBLE_SAVED_GAME_VERSION || player_struct_version < COMPATIBLE_PLAYER_STRUCT_VERSION) { - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{TXT_ERROR_PLR_VERSION}); + struct error_invalid_player_file_version : passive_messagebox + { + error_invalid_player_file_version() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{TXT_ERROR_PLR_VERSION}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return -1; } @@ -923,7 +937,14 @@ int read_player_file() } if (shareware_file == -1) { - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Error invalid or unknown\nplayerfile-size"}); + struct error_invalid_player_file_size : passive_messagebox + { + error_invalid_player_file_size() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{"Error invalid or unknown\nplayerfile-size"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return -1; } @@ -960,7 +981,14 @@ int read_player_file() player_file_version = SWAPSHORT(player_file_version); if (player_file_version < COMPATIBLE_PLAYER_FILE_VERSION) { - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{TXT_ERROR_PLR_VERSION}); + struct error_invalid_player_file_version : passive_messagebox + { + error_invalid_player_file_version() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{TXT_ERROR_PLR_VERSION}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return -1; } @@ -1117,7 +1145,14 @@ int read_player_file() if (i!=get_lifetime_checksum (PlayerCfg.NetlifeKills,PlayerCfg.NetlifeKilled)) { PlayerCfg.NetlifeKills=0; PlayerCfg.NetlifeKilled=0; - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie("Shame on me"), menu_subtitle{"Trying to cheat eh?"}); + struct error_invalid_player_file_checksum : passive_messagebox + { + error_invalid_player_file_checksum() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"Lifetime kill error"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); rewrite_it=1; } } diff --git a/similar/main/state.cpp b/similar/main/state.cpp index f1e3fdbae..fa0786ebf 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -919,7 +919,14 @@ static d_game_unique_state::save_slot state_get_savegame_filename(d_game_unique_ if (!dsc && nsaves < 1) { - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"No saved games were found!"}); + struct error_no_saves_found : passive_messagebox + { + error_no_saves_found() : + passive_messagebox(menu_title{nullptr}, menu_subtitle{"No saved games were found!"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return d_game_unique_state::save_slot::None; } @@ -1127,9 +1134,26 @@ int state_save_all_sub(const char *filename, const char *desc) #endif auto fp = PHYSFSX_openWriteBuffered(filename); - if ( !fp ) { - con_printf(CON_URGENT, "Failed to open %s: %s", filename, PHYSFS_getLastError()); - nm_messagebox_str(menu_title{nullptr}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Error writing savegame.\nPossibly out of disk\nspace."}); + if (!fp) + { + const auto errstr = PHYSFS_getLastError(); + con_printf(CON_URGENT, "Failed to open %s: %s", filename, errstr); + struct error_writing_savegame : + std::array, + passive_messagebox + { + error_writing_savegame(const char *filename, const char *errstr) : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{prepare_subtitle(*this, filename, errstr)}, "Return to unsaved game", grd_curscreen->sc_canvas) + { + } + static const char *prepare_subtitle(std::array &b, const char *filename, const char *errstr) + { + auto r = b.data(); + std::snprintf(r, b.size(), "Failed to write savegame\n%s\n\n%s", filename, errstr); + return r; + } + }; + run_blocking_newmenu(filename, errstr); return 0; } @@ -1735,7 +1759,14 @@ int state_restore_all_sub(const d_level_shared_destructible_light_state &LevelSh PHYSFS_read(fp, mission_pathname.full.data(), mission_pathname.full.size(), 1); if (mission_pathname.full.back()) { - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Unable to load game\nUnrecognized mission name format"}); + struct error_unknown_mission_format : passive_messagebox + { + error_unknown_mission_format() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{"Unable to load game\nUnrecognized mission name format"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); return 0; } } @@ -1747,7 +1778,16 @@ int state_restore_all_sub(const d_level_shared_destructible_light_state &LevelSh #endif break; default: /* Save game written by a future version of Rebirth. ABI unknown. */ - nm_messagebox_str(menu_title{TXT_ERROR}, nm_messagebox_tie(TXT_OK), menu_subtitle{"Unable to load game\nUnrecognized save game format"}); + { + struct error_unknown_save_format : passive_messagebox + { + error_unknown_save_format() : + passive_messagebox(menu_title{TXT_ERROR}, menu_subtitle{"Unable to load game\nUnrecognized save game format"}, TXT_OK, grd_curscreen->sc_canvas) + { + } + }; + run_blocking_newmenu(); + } return 0; } diff --git a/similar/main/switch.cpp b/similar/main/switch.cpp index b2f6561e0..09c2497fe 100644 --- a/similar/main/switch.cpp +++ b/similar/main/switch.cpp @@ -399,12 +399,6 @@ window_event_result check_trigger_sub(object &plrobj, const trgnum_t trigger_num result = ExitSecretLevel(); } return std::max(result, window_event_result::handled); - } else { -#if DXX_USE_EDITOR - nm_messagebox_str(menu_title{"Yo!"}, "You have hit the exit trigger!", menu_subtitle{""}); - #else - Int3(); //level num == 0, but no editor! - #endif } return std::max(result, window_event_result::handled); break;