The Battle for Wesnoth  1.15.6+dev
play_controller.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3  wesnoth playlevel Copyright (C) 2003 by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #pragma once
17 
18 #include "controller_base.hpp"
19 #include "game_end_exceptions.hpp"
20 #include "help/help.hpp"
22 #include "menu_events.hpp"
23 #include "mouse_events.hpp"
24 #include "persist_manager.hpp"
25 #include "terrain/type_data.hpp"
26 #include "tod_manager.hpp"
27 #include "game_state.hpp"
28 
29 #include <set>
30 
31 class game_display;
32 class game_data;
33 class team;
34 class unit;
35 class replay;
36 class replay_controller;
37 class saved_game;
38 struct mp_game_settings;
41 
42 namespace actions {
43  class undo_list;
44 }
45 
46 namespace font {
47  struct floating_label_context;
48 }
49 
50 namespace game_events {
51  class manager;
52  class wml_event_pump;
53  class wml_menu_item;
54 } // namespace game_events
55 
56 namespace soundsource {
57  class manager;
58 } // namespace soundsource
59 
60 namespace statistics {
61  struct scenario_context;
62 } // namespace statistics
63 
64 namespace pathfind {
65  class manager;
66 }
67 
68 namespace tooltips {
69  struct manager;
70 } // namespace tooltips
71 
72 namespace wb {
73  class manager; // whiteboard manager
74 } // namespace wb
75 
76 // Holds gamestate related objects
77 class game_state;
78 
80 {
81 public:
82  play_controller(const config& level, saved_game& state_of_game,
83  const ter_data_cache& tdata, bool skip_replay);
84  virtual ~play_controller();
85 
86  //event handler, overridden from observer
87  //there is nothing to handle in this class actually but that might change in the future
88  virtual void handle_generic_event(const std::string& /*name*/) override {}
89 
90  bool can_undo() const;
91  bool can_redo() const;
92 
93  void undo();
94  void redo();
95 
96  void load_game();
97 
98  void save_game();
99  void save_game_auto(const std::string& filename);
100  void save_replay();
101  void save_replay_auto(const std::string& filename);
102  void save_map();
103  replay& get_replay();
104 
105  void init_side_begin();
106 
107  /**
108  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
109  */
110  void maybe_do_init_side();
111 
112  /**
113  * Called by replay handler or init_side() to do actual work for turn change.
114  */
115  void do_init_side();
116 
117  void init_side_end();
118 
119  virtual void force_end_turn() = 0;
120  virtual void check_objectives() = 0;
121 
122  virtual void on_not_observer() = 0;
123 
124  /**
125  * Asks the user whether to continue on an OOS error.
126  *
127  * @throw quit_game_exception If the user wants to abort.
128  */
129  virtual void process_oos(const std::string& msg) const;
130 
132  gamestate().end_level_data_ = data;
133  }
135  gamestate().end_level_data_ = boost::none;
136  }
137  bool is_regular_game_end() const {
138  return gamestate().end_level_data_.get_ptr() != nullptr;
139  }
141  return *gamestate().end_level_data_;
142  }
143  const std::vector<team>& get_teams_const() const {
144  return gamestate().board_.teams_;
145  }
146 
147  const unit_map& get_units_const() const {
148  return gamestate().board_.units();
149  }
150 
151  const gamemap& get_map_const() const{
152  return gamestate().board_.map();
153  }
155  return gamestate().tod_manager_;
156  }
157 
158  bool is_observer() const {
159  return gamestate().board_.is_observer();
160  }
161 
162  bool do_healing() const {
163  return gamestate().do_healing_;
164  }
165 
166  void set_do_healing(bool do_healing) {
167  gamestate().do_healing_ = do_healing;
168  }
169 
171  return *gamestate_;
172  }
173  const game_state& gamestate() const {
174  return *gamestate_;
175  }
176 
177  /**
178  * Checks to see if a side has won.
179  *
180  * This will also remove control of villages from sides with dead leaders.
181  */
182  void check_victory();
183 
184  std::size_t turn() const {return gamestate().tod_manager_.turn();}
185 
186  /**
187  * Returns the number of the side whose turn it is.
188  *
189  * Numbering starts at one.
190  */
191  int current_side() const { return gamestate_->player_number_; }
192 
193  /**
194  * Builds the snapshot config from members and their respective configs.
195  */
196  config to_config() const;
197 
198  bool is_skipping_replay() const { return skip_replay_; }
199  void toggle_skipping_replay();
200  bool is_linger_mode() const { return linger_; }
201  void do_autosave();
202 
203  bool is_skipping_story() const { return skip_story_; }
204 
205  void do_consolesave(const std::string& filename);
206 
207  events::mouse_handler& get_mouse_handler_base() override;
208  events::menu_handler& get_menu_handler() { return menu_handler_; }
209 
210  std::shared_ptr<wb::manager> get_whiteboard() const;
211  const mp_game_settings& get_mp_settings();
212  game_classification& get_classification();
213  int get_server_request_number() const { return gamestate().server_request_number_; }
214  void increase_server_request_number() { ++gamestate().server_request_number_; }
215 
217 
218  int get_ticks() const;
219 
220  virtual soundsource::manager* get_soundsource_man() override;
221  virtual plugins_context* get_plugins_context() override;
222  hotkey::command_executor* get_hotkey_command_executor() override;
223 
225 
226  bool is_browsing() const override;
227  bool is_lingering() const { return linger_; }
228 
229  class hotkey_handler;
230 
231  virtual replay_controller * get_replay_controller() const { return nullptr; }
232  bool is_replay() const { return get_replay_controller() != nullptr; }
233 
235  {
236  return level_["name"].t_str();
237  }
238 
239  bool get_disallow_recall() const
240  {
241  return level_["disallow_recall"].to_bool();
242  }
243 
245  {
246  return level_["loaded_resources"].str();
247  }
248 
250  {
251  return gamestate_->get_game_data()->get_theme();
252  }
253 
254  virtual bool should_return_to_play_side() const
255  {
256  return is_regular_game_end();
257  }
258 
260  {
261  if(should_return_to_play_side() && !linger_ ) {
262  throw return_to_play_side_exception();
263  }
264  }
265 
266  virtual void play_side_impl() {}
267 
268  void play_side();
269 
270  team& current_team();
271  const team& current_team() const;
272 
273  bool can_use_synced_wml_menu() const;
274  std::set<std::string> all_players() const;
275  int ticks() const { return ticks_; }
276  game_display& get_display() override;
277 
278  void update_savegame_snapshot() const;
279  /**
280  * Changes the UI for this client to the passed side index.
281  */
282  void update_gui_to_player(const int team_index, const bool observe = false);
283 
284  virtual bool is_networked_mp() const { return false; }
285  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
286  virtual bool receive_from_wesnothd(config&) const { return false; }
287  /// Reevaluate [show_if] conditions and build a new objectives string.
288  void refresh_objectives() const;
289  void show_objectives() const;
290 
292  {
296  };
297 
298  saved_game& get_saved_game() { return saved_game_; }
299 
300 protected:
302  void play_slice_catch();
303  bool have_keyboard_focus() override;
304  void process_focus_keydown_event(const SDL_Event& event) override;
305  void process_keydown_event(const SDL_Event& event) override;
306  void process_keyup_event(const SDL_Event& event) override;
307 
308  void init_managers();
309  ///preload events cannot be synced
310  void fire_preload();
311  void fire_prestart();
312  void fire_start();
313  void start_game();
314  virtual void init_gui();
315  void finish_side_turn();
316  void finish_turn(); //this should not throw an end turn or end level exception
317  bool enemies_visible() const;
318 
319  void enter_textbox();
320  void tab();
321 
322 
323  bool is_team_visible(int team_num, bool observer) const;
324  /// returns 0 if no such team was found.
325  int find_last_visible_team() const;
326 
327 private:
328  const int ticks_;
329 
330 protected:
331  //gamestate
333  std::unique_ptr<game_state> gamestate_;
336 
337  //managers
338  std::unique_ptr<tooltips::manager> tooltips_manager_;
339 
340  //whiteboard manager
341  std::shared_ptr<wb::manager> whiteboard_manager_;
342 
343  //plugins context
344  std::unique_ptr<plugins_context> plugins_context_;
345 
346  //more managers
347  std::unique_ptr<font::floating_label_context> labels_manager_;
351  std::unique_ptr<hotkey_handler> hotkey_handler_;
352  std::unique_ptr<soundsource::manager> soundsources_manager_;
354 
355  //other objects
356  std::unique_ptr<game_display> gui_;
357  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
358  const std::unique_ptr<const statistics::scenario_context> statistics_context_;
359  actions::undo_list& undo_stack() { return *gamestate().undo_stack_; }
360  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
361  std::unique_ptr<replay> replay_;
362 
365  bool linger_;
366  /**
367  * Whether we did init sides in this session
368  * (false = we did init sides before we reloaded the game).
369  */
371  //the displayed location when we load a game.
373  const std::string& select_music(bool victory) const;
374 
375  void reset_gamestate(const config& level, int replay_pos);
376 
377 private:
378 
379  void init(const config& level);
380 
383  std::vector<std::string> victory_music_;
384  std::vector<std::string> defeat_music_;
385 
387 
388 protected:
389  mutable bool ignore_replay_errors_;
391  virtual void sync_end_turn() {}
392  virtual void check_time_over();
393  virtual void update_viewing_player() = 0;
394  void play_turn();
395 };
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()
const ter_data_cache & tdata_
This class represents a single unit of a specific type.
Definition: unit.hpp:129
std::unique_ptr< game_display > gui_
bool victory_when_enemies_defeated_
Note: Specific to sdl_ttf.
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)
const unit_map & get_units_const() const
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
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 ...
const end_level_data & get_end_level_data_const() const
persist_manager persist_
std::unique_ptr< tooltips::manager > tooltips_manager_
events::menu_handler menu_handler_
const tod_manager & get_tod_manager_const() const
bool get_disallow_recall() const
int get_server_request_number() const
std::unique_ptr< game_state > gamestate_
bool is_lingering() const
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:44
struct utils::detail::formula_initer init
const std::unique_ptr< const statistics::scenario_context > statistics_context_
bool is_linger_mode() const
Implements a quit confirmation dialog.
bool is_regular_game_end() const
Encapsulates the map of the game.
Definition: map.hpp:36
std::string theme() const
void pump()
Definition: events.cpp:475
bool is_observer() const
Encapsulates the map of the game.
Definition: location.hpp:42
Domain specific events.
Definition: action_wml.cpp:89
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
hotkey::scope_changer scope_
std::shared_ptr< wb::manager > whiteboard_manager_
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()
virtual void handle_generic_event(const std::string &) override
std::string observer
virtual bool receive_from_wesnothd(config &) const
bool is_replay() const
Class to store the actions that a player can undo and redo.
Definition: undo.hpp:35
void maybe_throw_return_to_play_side() const
game_state & gamestate()
const std::unique_ptr< unit_experience_accelerator > xp_mod_
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 gamemap & get_map_const() const
const game_state & gamestate() const
Container associating units to locations.
Definition: map.hpp:99
std::string get_loaded_resources() const
std::vector< std::string > victory_music_
actions::undo_list * undo_stack
Definition: resources.cpp:32
std::size_t turn() const
const std::vector< team > & get_teams_const() const
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
Definition: display.hpp:48
virtual void play_side_impl()
bool init_side_done_now_
Whether we did init sides in this session (false = we did init sides before we reloaded the game)...
bool remove_from_carryover_on_defeat_
void increase_server_request_number()
std::shared_ptr< terrain_type_data > ter_data_cache
virtual void sync_end_turn()