The Battle for Wesnoth  1.19.5+dev
singleplayer.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "addon/manager_ui.hpp"
18 #include "config.hpp"
22 #include "game_launcher.hpp"
24 #include "gui/dialogs/message.hpp"
26 #include "gui/widgets/retval.hpp"
27 #include "wml_exception.hpp"
28 
29 static lg::log_domain log_engine("engine");
30 #define ERR_NG LOG_STREAM(err, log_engine)
31 
32 namespace sp
33 {
34 bool select_campaign(saved_game& state, jump_to_campaign_info jump_to_campaign)
35 {
36  while(true) {
37  ng::create_engine create_eng(state);
38  create_eng.set_current_level_type(level_type::type::sp_campaign);
39 
40  const std::vector<ng::create_engine::level_ptr> campaigns =
41  create_eng.get_levels_by_type_unfiltered(level_type::type::sp_campaign);
42 
43  if(campaigns.empty()) {
44  gui2::show_error_message(_("No campaigns are available."));
45  return false;
46  }
47 
48  std::string random_mode = "", difficulty = "";
49 
50  // No campaign selected from command line
51  if(jump_to_campaign.campaign_id.empty()) {
52  gui2::dialogs::campaign_selection dlg(create_eng);
53 
54  try {
55  dlg.show();
56  } catch(const wml_exception& e) {
57  e.show();
58  return false;
59  }
60 
61  if(dlg.get_retval() == gui2::retval::OK) {
62  switch(dlg.get_rng_mode()) {
64  random_mode = "";
65  break;
67  random_mode = "deterministic";
68  break;
70  random_mode = "biased";
71  break;
72  }
73  difficulty = dlg.get_difficulty();
74  } else {
76  manage_addons();
77  }
78  return false;
79  }
80 
81  } else {
82  // Don't reset the campaign_id_ so we can know
83  // if we should quit the game or return to the main menu
84 
85  // Checking for valid campaign name
86  const auto campaign = std::find_if(campaigns.begin(), campaigns.end(), [&jump_to_campaign](ng::create_engine::level_ptr level) {
87  return level->data()["id"] == jump_to_campaign.campaign_id;
88  });
89 
90  // Didn't find a campaign with that id
91  if(campaign == campaigns.end()) {
92  ERR_NG << "No such campaign id to jump to: [" << jump_to_campaign.campaign_id << "]";
93  return false;
94  }
95 
96  create_eng.set_current_level(std::distance(campaigns.begin(), campaign));
97  }
98 
99  state.classification().random_mode = random_mode;
100 
101  const auto selected_difficulty = difficulty;
102 
103  if(selected_difficulty == "FAIL") return false;
104  if(selected_difficulty == "CANCEL") {
105  if(!jump_to_campaign.campaign_id.empty()) {
106  jump_to_campaign.campaign_id = "";
107  }
108 
109  // Canceled difficulty dialog, relaunch the campaign selection dialog
110  return select_campaign(state, jump_to_campaign);
111  }
112 
113  create_eng.prepare_for_era_and_mods();
114  create_eng.prepare_for_campaign(selected_difficulty);
115 
116  if(!jump_to_campaign.scenario_id.empty()) {
118  config {"next_scenario", jump_to_campaign.scenario_id}
119  );
120  }
121 
122  if(!state.valid()) {
123  ERR_NG << "Cannot load scenario with id=" << state.get_scenario_id();
124  return false;
125  }
126 
127  if(configure_campaign(state, create_eng)) {
128  break;
129  }
130  }
131 
132  return true;
133 }
134 
136 {
137  // We create the config engine here in order to ensure values like use_map_settings are set correctly
138  // TODO: should this be passed to this function instead of created here?
139  ng::configure_engine config_eng(create_eng.get_state());
140 
141  // TODO: needed?
142  config_eng.update_initial_cfg(create_eng.current_level().data());
143 
144  if(!gui2::dialogs::sp_options_configure::execute(create_eng, config_eng)) {
145  return false;
146  }
147 
148  create_eng.get_parameters();
149  create_eng.prepare_for_new_level();
150 
151  ng::connect_engine connect_eng(state, true, nullptr);
152  connect_eng.start_game();
153 
154  return true;
155 }
156 
157 } // end namespace sp
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
const std::string & get_difficulty() const
bool show(const unsigned auto_close_time=0)
Shows the window.
int get_retval() const
Returns the cached window exit code.
static bool execute(ng::create_engine &create_engine, ng::configure_engine &config_engine)
Execute function.
void update_initial_cfg(const config &cfg)
std::shared_ptr< level > level_ptr
void set_current_level_type(const level_type::type type)
saved_game & get_state()
void prepare_for_campaign(const std::string &difficulty="")
std::vector< level_ptr > get_levels_by_type_unfiltered(level_type::type type) const
const mp_game_settings & get_parameters()
void set_current_level(const std::size_t index)
void prepare_for_era_and_mods()
level & current_level() const
const config & data() const
game_classification & classification()
Definition: saved_game.hpp:56
void set_carryover_sides_start(config carryover_sides_start)
Definition: saved_game.cpp:164
std::string get_scenario_id() const
Definition: saved_game.cpp:679
bool valid() const
Definition: saved_game.cpp:583
Definitions for the interface to Wesnoth Markup Language (WML).
static std::string _(const char *str)
Definition: gettext.hpp:93
bool manage_addons()
Shows the add-ons server connection dialog, for access to the various management front-ends.
Definition: manager_ui.cpp:228
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
Definition: message.cpp:201
@ OK
Dialog was closed with the OK button.
Definition: retval.hpp:35
bool select_campaign(saved_game &state, jump_to_campaign_info jump_to_campaign)
bool configure_campaign(saved_game &state, ng::create_engine &create_eng)
static lg::log_domain log_engine("engine")
#define ERR_NG
std::string campaign_id
The ID of the campaign to launch.
std::string scenario_id
The ID of the scenario within the campaign to jump to.
Helper class, don't construct this directly.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define e