The Battle for Wesnoth  1.17.14+dev
play_controller.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2022
3  by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
4  Copyright (C) 2003 by David White <dave@whitevine.net>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #pragma once
18 
19 #include "controller_base.hpp"
20 #include "game_end_exceptions.hpp"
21 #include "help/help.hpp"
23 #include "menu_events.hpp"
24 #include "mouse_events.hpp"
25 #include "persist_manager.hpp"
26 #include "tod_manager.hpp"
27 #include "game_state.hpp"
28 #include <optional>
29 
30 #include <set>
31 
32 class game_display;
33 class game_data;
34 class team;
35 class unit;
36 class replay;
37 class replay_controller;
38 class saved_game;
39 struct mp_game_settings;
42 
43 namespace actions {
44  class undo_list;
45 }
46 
47 namespace font {
48  struct floating_label_context;
49 }
50 
51 namespace game_events {
52  class manager;
53  class wml_event_pump;
54  class wml_menu_item;
55 } // namespace game_events
56 
57 namespace soundsource {
58  class manager;
59 } // namespace soundsource
60 
61 namespace statistics {
62  struct scenario_context;
63 } // namespace statistics
64 
65 namespace pathfind {
66  class manager;
67 }
68 
69 namespace tooltips {
70  class manager;
71 } // namespace tooltips
72 
73 namespace wb {
74  class manager; // whiteboard manager
75 } // namespace wb
76 
77 // Holds gamestate related objects
78 class game_state;
79 
81 {
82 public:
84  saved_game& state_of_game,
85  bool skip_replay,
86  bool start_faded = false);
87  virtual ~play_controller();
88 
89  //event handler, overridden from observer
90  //there is nothing to handle in this class actually but that might change in the future
91  virtual void handle_generic_event(const std::string& /*name*/) override {}
92 
93  bool can_undo() const;
94  bool can_redo() const;
95 
96  void undo();
97  void redo();
98 
99  void load_game();
100 
101  void save_game();
102  void save_game_auto(const std::string& filename);
103  void save_replay();
104  void save_replay_auto(const std::string& filename);
105  void save_map();
106  replay& get_replay();
107 
108  void init_side_begin();
109 
110  /**
111  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
112  */
113  void maybe_do_init_side();
114 
115  /**
116  * Called by replay handler or init_side() to do actual work for turn change.
117  */
118  void do_init_side();
119 
120  void init_side_end();
121 
122  virtual void force_end_turn() = 0;
123  virtual void check_objectives() = 0;
124 
125  virtual void on_not_observer() = 0;
126 
127  /**
128  * Asks the user whether to continue on an OOS error.
129  *
130  * @throw quit_game_exception If the user wants to abort.
131  */
132  virtual void process_oos(const std::string& msg) const;
133 
135  {
136  gamestate().end_level_data_ = data;
137  }
138 
140  {
141  gamestate().end_level_data_.reset();
142  }
143 
144  bool is_regular_game_end() const
145  {
146  return gamestate().end_level_data_.has_value();
147  }
148 
149  bool check_regular_game_end();
150 
152  {
153  return *gamestate().end_level_data_;
154  }
155 
156  std::vector<team>& get_teams()
157  {
158  return gamestate().board_.teams();
159  }
160 
161  const std::vector<team>& get_teams() const
162  {
163  return gamestate().board_.teams();
164  }
165 
166  const unit_map& get_units() const
167  {
168  return gamestate().board_.units();
169  }
170 
172  {
173  return gamestate().board_.units();
174  }
175 
176  const gamemap& get_map() const
177  {
178  return gamestate().board_.map();
179  }
180 
182  {
183  return gamestate().tod_manager_;
184  }
185 
186  bool is_observer() const
187  {
188  return gamestate().board_.is_observer();
189  }
190 
191  bool do_healing() const
192  {
193  return gamestate().do_healing_;
194  }
195 
196  void set_do_healing(bool do_healing)
197  {
198  gamestate().do_healing_ = do_healing;
199  }
200 
202  {
203  return *gamestate_;
204  }
205 
206  const game_state& gamestate() const
207  {
208  return *gamestate_;
209  }
210 
211  /**
212  * Checks to see if a side has won.
213  *
214  * This will also remove control of villages from sides with dead leaders.
215  */
216  void check_victory();
217 
218  std::size_t turn() const {return gamestate().tod_manager_.turn();}
219 
220  /**
221  * Returns the number of the side whose turn it is.
222  *
223  * Numbering starts at one.
224  */
225  int current_side() const { return gamestate_->player_number_; }
226 
227  /**
228  * Builds the snapshot config from members and their respective configs.
229  */
230  config to_config() const;
231 
232  bool is_skipping_replay() const { return skip_replay_; }
233  void toggle_skipping_replay();
234  void do_autosave();
235 
236  bool is_skipping_story() const { return skip_story_; }
237 
238  void do_consolesave(const std::string& filename);
239 
240  events::mouse_handler& get_mouse_handler_base() override;
241  events::menu_handler& get_menu_handler() { return menu_handler_; }
242 
243  std::shared_ptr<wb::manager> get_whiteboard() const;
244  const mp_game_settings& get_mp_settings();
245  game_classification& get_classification();
246  int get_server_request_number() const { return gamestate().server_request_number_; }
247  void increase_server_request_number() { ++gamestate().server_request_number_; }
248 
250 
251  int get_ticks() const;
252 
253  virtual soundsource::manager* get_soundsource_man() override;
254  virtual plugins_context* get_plugins_context() override;
255  hotkey::command_executor* get_hotkey_command_executor() override;
256 
258 
259  bool is_browsing() const override;
260 #
261  class hotkey_handler;
262 
263  virtual replay_controller * get_replay_controller() const { return nullptr; }
264  bool is_replay() const { return get_replay_controller() != nullptr; }
265 
267  {
268  return level_["name"].t_str();
269  }
270 
271  bool get_disallow_recall() const
272  {
273  return level_["disallow_recall"].to_bool();
274  }
275 
276  std::string get_loaded_resources() const
277  {
278  return level_["loaded_resources"].str();
279  }
280 
281  std::string theme() const
282  {
283  return gamestate_->get_game_data()->get_theme();
284  }
285 
286  virtual bool should_return_to_play_side() const
287  {
288  return is_regular_game_end();
289  }
290 
291  void maybe_throw_return_to_play_side() const;
292 
293  virtual void play_side_impl() {}
294 
295  void play_side();
296 
297  team& current_team();
298  const team& current_team() const;
299 
300  bool can_use_synced_wml_menu() const;
301  std::set<std::string> all_players() const;
302  int ticks() const { return ticks_; }
303  game_display& get_display() override;
304 
305  void update_savegame_snapshot() const;
306  /**
307  * Changes the UI for this client to the passed side index.
308  */
309  void update_gui_to_player(const int team_index, const bool observe = false);
310 
311  virtual bool is_networked_mp() const { return false; }
312  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
313  virtual bool receive_from_wesnothd(config&) const { return false; }
314  /** Reevaluate [show_if] conditions and build a new objectives string. */
315  void refresh_objectives() const;
316  void show_objectives() const;
317 
319  {
323  };
324 
325  saved_game& get_saved_game() { return saved_game_; }
326 
327  bool is_during_turn() const;
328  bool is_linger_mode() const;
329 
330 protected:
332  void play_slice_catch();
333  bool have_keyboard_focus() override;
334  void process_focus_keydown_event(const SDL_Event& event) override;
335  void process_keydown_event(const SDL_Event& event) override;
336  void process_keyup_event(const SDL_Event& event) override;
337 
338  void init_managers();
339  /** preload events cannot be synced */
340  void fire_preload();
341  void fire_prestart();
342  void fire_start();
343  void start_game();
344  virtual void init_gui();
345  void finish_side_turn_events();
346  void finish_turn(); //this should not throw an end turn or end level exception
347  bool enemies_visible() const;
348 
349  void enter_textbox();
350  void textbox_move_vertically(bool up);
351  void tab();
352 
353 
354  bool is_team_visible(int team_num, bool observer) const;
355  /** returns 0 if no such team was found. */
356  int find_last_visible_team() const;
357 
358 private:
359  const int ticks_;
360 
361 protected:
362  //gamestate
363  std::unique_ptr<game_state> gamestate_;
366 
367  //managers
369 
370  //whiteboard manager
371  std::shared_ptr<wb::manager> whiteboard_manager_;
372 
373  //plugins context
374  std::unique_ptr<plugins_context> plugins_context_;
375 
376  //more managers
377  std::unique_ptr<font::floating_label_context> labels_manager_;
381  std::unique_ptr<hotkey_handler> hotkey_handler_;
382  std::unique_ptr<soundsource::manager> soundsources_manager_;
384 
385  //other objects
386  std::unique_ptr<game_display> gui_;
387  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
388  const std::unique_ptr<const statistics::scenario_context> statistics_context_;
389  actions::undo_list& undo_stack() { return *gamestate().undo_stack_; }
390  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
391  std::unique_ptr<replay> replay_;
392 
395  /**
396  * Whether we did init sides in this session
397  * (false = we did init sides before we reloaded the game).
398  */
401  //the displayed location when we load a game.
403  // Whether to start with the display faded to black
405 
406  const std::string& select_music(bool victory) const;
407 
408  void reset_gamestate(const config& level, int replay_pos);
409 
410 private:
411 
412  void init(const config& level);
413 
414  /**
415  * This shows a warning dialog if either [scenario]next_scenario or any [endlevel]next_scenario would lead to an "Unknown Scenario" dialog.
416  */
417  void check_next_scenario_is_known();
418 
421  std::vector<std::string> victory_music_;
422  std::vector<std::string> defeat_music_;
423 
425 
426 protected:
427  mutable bool ignore_replay_errors_;
428  /// true when the controller of the currently playing side has changed.
429  /// this can mean for example:
430  /// - The currently active side was reassigned from/to another player in a mp game
431  /// - The replay controller was disabled ('continue play' button)
432  /// - The currently active side was droided / undroided.
433  /// - A side was set to idle.
435  virtual void sync_end_turn() {}
436  virtual void check_time_over();
437  virtual void update_viewing_player() = 0;
438 };
bool player_type_changed_
true when the controller of the currently playing side has changed.
virtual replay_controller * get_replay_controller() const
virtual bool should_return_to_play_side() const
std::unique_ptr< soundsource::manager > soundsources_manager_
help::help_manager help_manager_
saved_game & get_saved_game()
This class represents a single unit of a specific type.
Definition: unit.hpp:133
std::unique_ptr< game_display > gui_
bool victory_when_enemies_defeated_
const unit_map & get_units() const
Collection of helper functions relating to Pango formatting.
events::mouse_handler mouse_handler_
std::unique_ptr< plugins_context > plugins_context_
bool is_skipping_replay() const
std::unique_ptr< replay > replay_
std::unique_ptr< hotkey_handler > hotkey_handler_
void set_do_healing(bool do_healing)
std::string_view data
Definition: picture.cpp:206
const gamemap & get_map() const
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
bool do_healing() const
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
controller_base framework: controller_base is roughly analogous to a "dialog" class in a GUI toolkit ...
persist_manager persist_
bool did_autosave_this_turn_
Whether we did init sides in this session (false = we did init sides before we reloaded the game)...
events::menu_handler menu_handler_
bool get_disallow_recall() const
int get_server_request_number() const
std::unique_ptr< game_state > gamestate_
saved_game & saved_game_
std::vector< std::string > defeat_music_
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:75
struct utils::detail::formula_initer init
const std::unique_ptr< const statistics::scenario_context > statistics_context_
const hotkey::scope_changer scope_
Implements a quit confirmation dialog.
bool is_regular_game_end() const
Encapsulates the map of the game.
Definition: map.hpp:171
std::vector< team > & get_teams()
std::string theme() const
void pump()
Process all events currently in the queue.
Definition: events.cpp:478
bool is_observer() const
Encapsulates the map of the game.
Definition: location.hpp:38
Domain specific events.
actions::undo_list & get_undo_stack()
void set_end_level_data(const end_level_data &data)
tooltips.
virtual bool is_networked_mp() const
map_location map_start_
const actions::undo_list & undo_stack() const
std::shared_ptr< wb::manager > whiteboard_manager_
The help implementation caches data parsed from the game_config.
Definition: help.hpp:40
t_string get_scenario_name() const
Additional information on the game outcome which can be provided by WML.
std::unique_ptr< font::floating_label_context > labels_manager_
actions::undo_list & undo_stack()
const end_level_data & get_end_level_data() const
virtual void handle_generic_event(const std::string &) override
std::string observer
virtual bool receive_from_wesnothd(config &) const
bool is_replay() const
tooltips::manager tooltips_manager_
Class to store the actions that a player can undo and redo.
Definition: undo.hpp:34
game_state & gamestate()
const std::unique_ptr< unit_experience_accelerator > xp_mod_
const tod_manager & get_tod_manager() const
events::menu_handler & get_menu_handler()
int current_side() const
Returns the number of the side whose turn it is.
bool is_skipping_story() const
const game_state & gamestate() const
Container associating units to locations.
Definition: map.hpp:98
std::string get_loaded_resources() const
std::vector< std::string > victory_music_
actions::undo_list * undo_stack
Definition: resources.cpp:33
std::size_t turn() const
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
const std::vector< team > & get_teams() const
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
Definition: display.hpp:49
virtual void play_side_impl()
bool remove_from_carryover_on_defeat_
void increase_server_request_number()
unit_map & get_units()
virtual void sync_end_turn()