The Battle for Wesnoth  1.15.2+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 "floating_label.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 "terrain/type_data.hpp"
27 #include "tod_manager.hpp"
28 #include "game_state.hpp"
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 game_events {
48  class manager;
49  class wml_event_pump;
50  class wml_menu_item;
51 } // namespace game_events
52 
53 namespace soundsource {
54  class manager;
55 } // namespace soundsource
56 
57 namespace statistics {
58  struct scenario_context;
59 } // namespace statistics
60 
61 namespace pathfind {
62  class manager;
63 }
64 
65 namespace tooltips {
66  struct manager;
67 } // namespace tooltips
68 
69 namespace wb {
70  class manager; // whiteboard manager
71 } // namespace wb
72 
73 // Holds gamestate related objects
74 class game_state;
75 
77 {
78 public:
79  play_controller(const config& level, saved_game& state_of_game,
80  const ter_data_cache& tdata, bool skip_replay);
81  virtual ~play_controller();
82 
83  //event handler, overridden from observer
84  //there is nothing to handle in this class actually but that might change in the future
85  virtual void handle_generic_event(const std::string& /*name*/) override {}
86 
87  bool can_undo() const;
88  bool can_redo() const;
89 
90  void undo();
91  void redo();
92 
93  void load_game();
94 
95  void save_game();
96  void save_game_auto(const std::string& filename);
97  void save_replay();
98  void save_replay_auto(const std::string& filename);
99  void save_map();
100  replay& get_replay();
101 
102  void init_side_begin();
103 
104  /**
105  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
106  */
107  void maybe_do_init_side();
108 
109  /**
110  * Called by replay handler or init_side() to do actual work for turn change.
111  */
112  void do_init_side();
113 
114  void init_side_end();
115 
116  virtual void force_end_turn() = 0;
117  virtual void check_objectives() = 0;
118 
119  virtual void on_not_observer() = 0;
120 
121  /**
122  * Asks the user whether to continue on an OOS error.
123  *
124  * @throw quit_game_exception If the user wants to abort.
125  */
126  virtual void process_oos(const std::string& msg) const;
127 
128  void set_end_level_data(const end_level_data& data) {
129  gamestate().end_level_data_ = data;
130  }
132  gamestate().end_level_data_ = boost::none;
133  }
134  bool is_regular_game_end() const {
135  return gamestate().end_level_data_.get_ptr() != nullptr;
136  }
138  return *gamestate().end_level_data_;
139  }
140  const std::vector<team>& get_teams_const() const {
141  return gamestate().board_.teams_;
142  }
143 
144  const unit_map& get_units_const() const {
145  return gamestate().board_.units();
146  }
147 
148  const gamemap& get_map_const() const{
149  return gamestate().board_.map();
150  }
152  return gamestate().tod_manager_;
153  }
154 
155  bool is_observer() const {
156  return gamestate().board_.is_observer();
157  }
158 
159  bool do_healing() const {
160  return gamestate().do_healing_;
161  }
162 
163  void set_do_healing(bool do_healing) {
164  gamestate().do_healing_ = do_healing;
165  }
166 
168  return *gamestate_;
169  }
170  const game_state& gamestate() const {
171  return *gamestate_;
172  }
173 
174  /**
175  * Checks to see if a side has won.
176  *
177  * This will also remove control of villages from sides with dead leaders.
178  */
179  void check_victory();
180 
181  std::size_t turn() const {return gamestate().tod_manager_.turn();}
182 
183  /**
184  * Returns the number of the side whose turn it is.
185  *
186  * Numbering starts at one.
187  */
188  int current_side() const { return gamestate_->player_number_; }
189 
190  /**
191  * Builds the snapshot config from members and their respective configs.
192  */
193  config to_config() const;
194 
195  bool is_skipping_replay() const { return skip_replay_; }
196  void toggle_skipping_replay();
197  bool is_linger_mode() const { return linger_; }
198  void do_autosave();
199 
200  bool is_skipping_story() const { return skip_story_; }
201 
202  void do_consolesave(const std::string& filename);
203 
204  events::mouse_handler& get_mouse_handler_base() override;
205  events::menu_handler& get_menu_handler() { return menu_handler_; }
206 
207  std::shared_ptr<wb::manager> get_whiteboard() const;
208  const mp_game_settings& get_mp_settings();
209  game_classification& get_classification();
210  int get_server_request_number() const { return gamestate().server_request_number_; }
211  void increase_server_request_number() { ++gamestate().server_request_number_; }
212 
214 
215  int get_ticks() const;
216 
217  virtual soundsource::manager* get_soundsource_man() override;
218  virtual plugins_context* get_plugins_context() override;
219  hotkey::command_executor* get_hotkey_command_executor() override;
220 
222 
223  bool is_browsing() const override;
224  bool is_lingering() const { return linger_; }
225 
226  class hotkey_handler;
227 
228  virtual replay_controller * get_replay_controller() const { return nullptr; }
229  bool is_replay() const { return get_replay_controller() != nullptr; }
230 
232  {
233  return level_["name"].t_str();
234  }
235 
236  bool get_disallow_recall() const
237  {
238  return level_["disallow_recall"].to_bool();
239  }
240 
241  std::string theme() const
242  {
243  return gamestate_->get_game_data()->get_theme();
244  }
245 
246  virtual bool should_return_to_play_side() const
247  {
248  return is_regular_game_end();
249  }
250 
252  {
253  if(should_return_to_play_side() && !linger_ ) {
254  throw return_to_play_side_exception();
255  }
256  }
257 
258  virtual void play_side_impl() {}
259 
260  void play_side();
261 
262  team& current_team();
263  const team& current_team() const;
264 
265  bool can_use_synced_wml_menu() const;
266  std::set<std::string> all_players() const;
267  int ticks() const { return ticks_; }
268  game_display& get_display() override;
269 
270  void update_savegame_snapshot() const;
271  /**
272  * Changes the UI for this client to the passed side index.
273  */
274  void update_gui_to_player(const int team_index, const bool observe = false);
275 
276  virtual bool is_networked_mp() const { return false; }
277  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
278  virtual bool receive_from_wesnothd(config&) const { return false; }
279  /// Reevaluate [show_if] conditions and build a new objectives string.
280  void refresh_objectives() const;
281  void show_objectives() const;
282 
284  {
288  };
289 
290  saved_game& get_saved_game() { return saved_game_; }
291 
292 protected:
294  void play_slice_catch();
295  bool have_keyboard_focus() override;
296  void process_focus_keydown_event(const SDL_Event& event) override;
297  void process_keydown_event(const SDL_Event& event) override;
298  void process_keyup_event(const SDL_Event& event) override;
299 
300  void init_managers();
301  ///preload events cannot be synced
302  void fire_preload();
303  void fire_prestart();
304  void fire_start();
305  void start_game();
306  virtual void init_gui();
307  void finish_side_turn();
308  void finish_turn(); //this should not throw an end turn or end level exception
309  bool enemies_visible() const;
310 
311  void enter_textbox();
312  void tab();
313 
314 
315  bool is_team_visible(int team_num, bool observer) const;
316  /// returns 0 if no such team was found.
317  int find_last_visible_team() const;
318 
319 private:
320  const int ticks_;
321 
322 protected:
323  //gamestate
325  std::unique_ptr<game_state> gamestate_;
328 
329  //managers
330  std::unique_ptr<tooltips::manager> tooltips_manager_;
331 
332  //whiteboard manager
333  std::shared_ptr<wb::manager> whiteboard_manager_;
334 
335  //plugins context
336  std::unique_ptr<plugins_context> plugins_context_;
337 
338  //more managers
343  std::unique_ptr<hotkey_handler> hotkey_handler_;
344  std::unique_ptr<soundsource::manager> soundsources_manager_;
346 
347  //other objects
348  std::unique_ptr<game_display> gui_;
349  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
350  const std::unique_ptr<const statistics::scenario_context> statistics_context_;
351  actions::undo_list& undo_stack() { return *gamestate().undo_stack_; }
352  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
353  std::unique_ptr<replay> replay_;
354 
357  bool linger_;
358  /**
359  * Whether we did init sides in this session
360  * (false = we did init sides before we reloaded the game).
361  */
363  //the displayed location when we load a game.
365  const std::string& select_music(bool victory) const;
366 
367  void reset_gamestate(const config& level, int replay_pos);
368 
369 private:
370 
371  void init(const config& level);
372 
375  std::vector<std::string> victory_music_;
376  std::vector<std::string> defeat_music_;
377 
379 
380 protected:
381  mutable bool ignore_replay_errors_;
383  virtual void sync_end_turn() {}
384  virtual void check_time_over();
385  virtual void update_viewing_player() = 0;
386  void play_turn();
387 };
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_
font::floating_label_context labels_manager_
saved_game & get_saved_game()
const ter_data_cache & tdata_
This class represents a single unit of a specific type.
Definition: unit.hpp:99
std::unique_ptr< game_display > gui_
bool victory_when_enemies_defeated_
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_
structure which will hide all current floating labels, and cause floating labels instantiated after i...
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.
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()