diff --git a/src/cata_utility.h b/src/cata_utility.h index 38b8a1927b983..c31790defbfd1 100644 --- a/src/cata_utility.h +++ b/src/cata_utility.h @@ -10,6 +10,7 @@ #include #include +#include "optional.h" #include "units.h" class JsonIn; @@ -510,4 +511,23 @@ std::string join( const std::vector &strings, const std::string &jo int modulo( int v, int m ); +class on_out_of_scope +{ + private: + cata::optional> func; + public: + on_out_of_scope( const std::function &func ) : func( func ) { + } + + ~on_out_of_scope() { + if( func ) { + ( *func )(); + } + } + + void cancel() { + func.reset(); + } +}; + #endif // CAT_UTILITY_H diff --git a/src/main_menu.cpp b/src/main_menu.cpp index 21ebf6bbdc978..b777912d768bd 100644 --- a/src/main_menu.cpp +++ b/src/main_menu.cpp @@ -590,6 +590,11 @@ bool main_menu::opening_screen() } if( action == "UP" || action == "CONFIRM" ) { if( sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1 ) { + on_out_of_scope cleanup( []() { + g->gamemode.reset(); + g->u = avatar(); + world_generator->set_active_world( nullptr ); + } ); g->gamemode = get_special_game( static_cast( sel2 + 1 ) ); // check world WORLDPTR world = world_generator->make_new_world( static_cast( sel2 + 1 ) ); @@ -601,15 +606,12 @@ bool main_menu::opening_screen() g->setup(); } catch( const std::exception &err ) { debugmsg( "Error: %s", err.what() ); - g->gamemode.reset(); - g->u = avatar(); continue; } if( !g->gamemode->init() ) { - g->gamemode.reset(); - g->u = avatar(); continue; } + cleanup.cancel(); start = true; } } @@ -661,7 +663,7 @@ bool main_menu::opening_screen() if( action == "UP" || action == "CONFIRM" ) { if( sel2 == 0 ) { - get_options().show( true ); + get_options().show( false ); // The language may have changed- gracefully handle this. init_strings(); } else if( sel2 == 1 ) { @@ -758,6 +760,10 @@ bool main_menu::new_character_tab() } if( action == "UP" || action == "CONFIRM" ) { if( sel2 == 0 || sel2 == 2 || sel2 == 3 || sel2 == 4 ) { + on_out_of_scope cleanup( []() { + g->u = avatar(); + world_generator->set_active_world( nullptr ); + } ); // First load the mods, this is done by // loading the world. // Pick a world, suppressing prompts if it's "play now" mode. @@ -770,7 +776,6 @@ bool main_menu::new_character_tab() g->setup(); } catch( const std::exception &err ) { debugmsg( "Error: %s", err.what() ); - g->u = avatar(); continue; } character_type play_type = PLTYPE_CUSTOM; @@ -789,7 +794,6 @@ bool main_menu::new_character_tab() break; } if( !g->u.create( play_type ) ) { - g->u = avatar(); load_char_templates(); werase( w_background ); wrefresh( w_background ); @@ -802,9 +806,9 @@ bool main_menu::new_character_tab() wrefresh( w_background ); if( !g->start_game() ) { - g->u = avatar(); continue; } + cleanup.cancel(); start = true; } else if( sel2 == 1 ) { layer = 3; @@ -865,9 +869,12 @@ bool main_menu::new_character_tab() } } } else if( action == "RIGHT" || action == "CONFIRM" ) { + on_out_of_scope cleanup( []() { + g->u = avatar(); + world_generator->set_active_world( nullptr ); + } ); WORLDPTR world = world_generator->pick_world(); if( world == nullptr ) { - g->u = avatar(); continue; } world_generator->set_active_world( world ); @@ -875,11 +882,9 @@ bool main_menu::new_character_tab() g->setup(); } catch( const std::exception &err ) { debugmsg( "Error: %s", err.what() ); - g->u = avatar(); continue; } if( !g->u.create( PLTYPE_TEMPLATE, templates[sel3] ) ) { - g->u = avatar(); load_char_templates(); werase( w_background ); wrefresh( w_background ); @@ -890,9 +895,9 @@ bool main_menu::new_character_tab() werase( w_background ); wrefresh( w_background ); if( !g->start_game() ) { - g->u = avatar(); continue; } + cleanup.cancel(); start = true; } } @@ -1044,6 +1049,11 @@ bool main_menu::load_character_tab( bool transfer ) } if( action == "RIGHT" || action == "CONFIRM" ) { if( sel3 >= 0 && sel3 < static_cast( savegames.size() ) ) { + on_out_of_scope cleanup( []() { + g->u = avatar(); + world_generator->set_active_world( nullptr ); + } ); + werase( w_background ); wrefresh( w_background ); @@ -1057,11 +1067,11 @@ bool main_menu::load_character_tab( bool transfer ) g->setup(); } catch( const std::exception &err ) { debugmsg( "Error: %s", err.what() ); - g->u = avatar(); continue; } g->load( savegames[sel3] ); + cleanup.cancel(); start = true; } }