The Battle for Wesnoth  1.15.3+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 
131  void set_end_level_data(const end_level_data& data) {
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 
244  std::string theme() const
245  {
246  return gamestate_->get_game_data()->get_theme();
247  }
248 
249  virtual bool should_return_to_play_side() const
250  {
251  return is_regular_game_end();
252  }
253 
255  {
256  if(should_return_to_play_side() && !linger_ ) {
257  throw return_to_play_side_exception();
258  }
259  }
260 
261  virtual void play_side_impl() {}
262 
263  void play_side();
264 
265  team& current_team();
266  const team& current_team() const;
267 
268  bool can_use_synced_wml_menu() const;
269  std::set<std::string> all_players() const;
270  int ticks() const { return ticks_; }
271  game_display& get_display() override;
272 
273  void update_savegame_snapshot() const;
274  /**
275  * Changes the UI for this client to the passed side index.
276  */
277  void update_gui_to_player(const int team_index, const bool observe = false);
278 
279  virtual bool is_networked_mp() const { return false; }
280  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
281  virtual bool receive_from_wesnothd(config&) const { return false; }
282  /// Reevaluate [show_if] conditions and build a new objectives string.
283  void refresh_objectives() const;
284  void show_objectives() const;
285 
287  {
291  };
292 
293  saved_game& get_saved_game() { return saved_game_; }
294 
295 protected:
297  void play_slice_catch();
298  bool have_keyboard_focus() override;
299  void process_focus_keydown_event(const SDL_Event& event) override;
300  void process_keydown_event(const SDL_Event& event) override;
301  void process_keyup_event(const SDL_Event& event) override;
302 
303  void init_managers();
304  ///preload events cannot be synced
305  void fire_preload();
306  void fire_prestart();
307  void fire_start();
308  void start_game();
309  virtual void init_gui();
310  void finish_side_turn();
311  void finish_turn(); //this should not throw an end turn or end level exception
312  bool enemies_visible() const;
313 
314  void enter_textbox();
315  void tab();
316 
317 
318  bool is_team_visible(int team_num, bool observer) const;
319  /// returns 0 if no such team was found.
320  int find_last_visible_team() const;
321 
322 private:
323  const int ticks_;
324 
325 protected:
326  //gamestate
328  std::unique_ptr<game_state> gamestate_;
331 
332  //managers
333  std::unique_ptr<tooltips::manager> tooltips_manager_;
334 
335  //whiteboard manager
336  std::shared_ptr<wb::manager> whiteboard_manager_;
337 
338  //plugins context
339  std::unique_ptr<plugins_context> plugins_context_;
340 
341  //more managers
342  std::unique_ptr<font::floating_label_context> labels_manager_;
346  std::unique_ptr<hotkey_handler> hotkey_handler_;
347  std::unique_ptr<soundsource::manager> soundsources_manager_;
349 
350  //other objects
351  std::unique_ptr<game_display> gui_;
352  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
353  const std::unique_ptr<const statistics::scenario_context> statistics_context_;
354  actions::undo_list& undo_stack() { return *gamestate().undo_stack_; }
355  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
356  std::unique_ptr<replay> replay_;
357 
360  bool linger_;
361  /**
362  * Whether we did init sides in this session
363  * (false = we did init sides before we reloaded the game).
364  */
366  //the displayed location when we load a game.
368  const std::string& select_music(bool victory) const;
369 
370  void reset_gamestate(const config& level, int replay_pos);
371 
372 private:
373 
374  void init(const config& level);
375 
378  std::vector<std::string> victory_music_;
379  std::vector<std::string> defeat_music_;
380 
382 
383 protected:
384  mutable bool ignore_replay_errors_;
386  virtual void sync_end_turn() {}
387  virtual void check_time_over();
388  virtual void update_viewing_player() = 0;
389  void play_turn();
390 };
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:106
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:88
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::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()