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