1 /*
2    Copyright (C) 2008 - 2018 by the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY.
10 
11    See the COPYING file for more details.
12 */
13 
14 #include "game_initialization/singleplayer.hpp"
15 
16 #include "config.hpp"
17 #include "gui/dialogs/campaign_selection.hpp"
18 #include "gui/dialogs/message.hpp"
19 #include "gui/dialogs/multiplayer/mp_staging.hpp"
20 #include "gui/dialogs/sp_options_configure.hpp"
21 #include "gui/widgets/retval.hpp"
22 #include "wml_exception.hpp"
23 
24 static lg::log_domain log_engine("engine");
25 #define ERR_NG LOG_STREAM(err, log_engine)
26 
27 namespace sp
28 {
enter_create_mode(saved_game & state,jump_to_campaign_info jump_to_campaign)29 bool enter_create_mode(saved_game& state, jump_to_campaign_info jump_to_campaign)
30 {
31 	bool configure_canceled = false;
32 
33 	do {
34 		ng::create_engine create_eng(state);
35 
36 		create_eng.set_current_level_type(ng::level::TYPE::SP_CAMPAIGN);
37 
38 		const std::vector<ng::create_engine::level_ptr> campaigns =
39 			create_eng.get_levels_by_type_unfiltered(ng::level::TYPE::SP_CAMPAIGN);
40 
41 		if(campaigns.empty()) {
42 			gui2::show_error_message(_("No campaigns are available."));
43 			return false;
44 		}
45 
46 		std::string random_mode = "";
47 
48 		// No campaign selected from command line
49 		if(jump_to_campaign.campaign_id_.empty()) {
50 			gui2::dialogs::campaign_selection dlg(create_eng);
51 
52 			try {
53 				dlg.show();
54 			} catch(const wml_exception& e) {
55 				e.show();
56 				return false;
57 			}
58 
59 			if(dlg.get_retval() != gui2::retval::OK) {
60 				return false;
61 			}
62 
63 			if(dlg.get_deterministic()) {
64 				random_mode = "deterministic";
65 			}
66 		} else {
67 			// Don't reset the campaign_id_ so we can know
68 			// if we should quit the game or return to the main menu
69 
70 			// Checking for valid campaign name
71 			const auto campaign = std::find_if(campaigns.begin(), campaigns.end(), [&jump_to_campaign](ng::create_engine::level_ptr level) {
72 				return level->data()["id"] == jump_to_campaign.campaign_id_;
73 			});
74 
75 			// Didn't find a campaign with that id
76 			if(campaign == campaigns.end()) {
77 				ERR_NG << "No such campaign id to jump to: [" << jump_to_campaign.campaign_id_ << "]" << std::endl;
78 				return false;
79 			}
80 
81 			create_eng.set_current_level(std::distance(campaigns.begin(), campaign));
82 		}
83 
84 		state.classification().random_mode = random_mode;
85 
86 		const std::string selected_difficulty = create_eng.select_campaign_difficulty(jump_to_campaign.difficulty_);
87 
88 		if(selected_difficulty == "FAIL") return false;
89 		if(selected_difficulty == "CANCEL") {
90 			if(!jump_to_campaign.campaign_id_.empty()) {
91 				jump_to_campaign.campaign_id_ = "";
92 			}
93 
94 			// Canceled difficulty dialog, relaunch the campaign selection dialog
95 			return enter_create_mode(state, jump_to_campaign);
96 		}
97 
98 		create_eng.prepare_for_era_and_mods();
99 		create_eng.prepare_for_campaign(selected_difficulty);
100 
101 		if(!jump_to_campaign.scenario_id_.empty()) {
102 			state.set_carryover_sides_start(
103 				config {"next_scenario", jump_to_campaign.scenario_id_}
104 			);
105 		}
106 
107 		if(!state.valid()) {
108 			ERR_NG << "Cannot load scenario with id=" << state.get_scenario_id() << std::endl;
109 			return false;
110 		}
111 
112 		configure_canceled = !enter_configure_mode(state, create_eng);
113 
114 	} while (configure_canceled);
115 
116 	return true;
117 }
118 
enter_configure_mode(saved_game & state,ng::create_engine & create_eng)119 bool enter_configure_mode(saved_game& state, ng::create_engine& create_eng)
120 {
121 	// We create the config engine here in order to ensure values like use_map_settings are set correctly
122 	// TODO: should this be passed to this function instead of created here?
123 	ng::configure_engine config_eng(create_eng.get_state());
124 
125 	// TODO: needed?
126 	config_eng.update_initial_cfg(create_eng.current_level().data());
127 
128 	if(!gui2::dialogs::sp_options_configure::execute(create_eng, config_eng)) {
129 		return false;
130 	}
131 
132 	create_eng.get_parameters();
133 	create_eng.prepare_for_new_level();
134 
135 	enter_connect_mode(state);
136 
137 	return true;
138 }
139 
enter_connect_mode(saved_game & state)140 void enter_connect_mode(saved_game& state)
141 {
142 	ng::connect_engine connect_eng(state, true, nullptr);
143 	connect_eng.start_game();
144 }
145 
146 } // end namespace sp
147