-
-
Notifications
You must be signed in to change notification settings - Fork 991
/
game_display.hpp
345 lines (256 loc) · 9.74 KB
/
game_display.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
/*
Copyright (C) 2003 - 2014 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://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.
*/
/** @file */
#ifndef GAME_DISPLAY_H_INCLUDED
#define GAME_DISPLAY_H_INCLUDED
class config;
class tod_manager;
class team;
class unit;
class unit_map;
#include "animated.hpp"
#include "chat_events.hpp"
#include "display.hpp"
#include "pathfind/pathfind.hpp"
#include <deque>
// This needs to be separate from display.h because of the static
// singleton member, which will otherwise trigger link failure
// when building the editor.
class game_display : public display
{
public:
game_display(game_board& board, CVideo& video,
const tod_manager& tod_manager,
const config& theme_cfg,
const config& level);
static game_display* create_dummy_display(CVideo& video);
~game_display();
static game_display* get_singleton()
{
return static_cast<game_display*>(singleton_);
}
/**
* Update lighting settings.
*
* Should be called on every new turn.
*/
void new_turn();
/**
* Scrolls to the leader of a certain side.
*
* This will normally be the playing team.
*/
void scroll_to_leader(int side, SCROLL_TYPE scroll_type = ONSCREEN,bool force = true);
/**
* Function to display a location as selected.
*
* If a unit is in the location, and there is no unit in the currently
* highlighted hex, the unit will be displayed in the sidebar.
*/
virtual void select_hex(map_location hex);
/**
* Function to highlight a location.
*
* If a unit is in the location, it will be displayed in the sidebar.
* Selection is used when a unit has been clicked on, while highlighting is
* used when a location has been moused over.
*/
virtual void highlight_hex(map_location hex);
/**
* Change the unit to be displayed in the sidebar.
*
* This is used when selecting or highlighting is not wanted.
*/
void display_unit_hex(map_location hex);
/**
* Sets the paths that are currently displayed as available
* for the unit to move along.
* All other paths will be grayed out.
*/
void highlight_reach(const pathfind::paths &paths_list);
/**
* Add more paths to highlight. Print numbers where they overlap.
* Used only by Show Enemy Moves.
*/
void highlight_another_reach(const pathfind::paths &paths_list);
/** Reset highlighting of paths. */
void unhighlight_reach();
/**
* Sets the route along which footsteps are drawn to show movement of a
* unit. If NULL, no route is displayed. @a route does not have to remain
* valid after being set.
*/
void set_route(const pathfind::marked_route *route);
/** Function to float a label above a tile */
void float_label(const map_location& loc, const std::string& text,
int red, int green, int blue);
/**
* Function to return 2 half-hex footsteps images for the given location.
* Only loc is on the current route set by set_route.
*/
std::vector<surface> footsteps_images(const map_location& loc);
/** Draws the movement info (turns available) for a given location. */
void draw_movement_info(const map_location& loc);
/** Function to invalidate that unit status displayed on the sidebar. */
void invalidate_unit() { invalidateGameStatus_ = true; }
/** Same as invalidate_unit() if moving the displayed unit. */
void invalidate_unit_after_move(const map_location& src, const map_location& dst);
const time_of_day& get_time_of_day(const map_location& loc) const;
bool has_time_area() const;
protected:
/**
* game_display pre_draw does specific things related e.g. to unit rendering
* and calls the whiteboard pre-draw method.
*/
void pre_draw();
/**
* Calls the whiteboard's post-draw method.
*/
void post_draw();
void draw_invalidated();
void post_commit();
void draw_hex(const map_location& loc);
/**
* the list of units we need to look at, game_display adds fake units
*/
virtual std::vector<unit*> get_unit_list_for_invalidation();
public:
/** A temporary unit that can be placed on the map.
Temporary units can overlap units.
Adding the same unit twice isn't allowed.
The fake_unit owns its underlying unit and when
it goes out of scope it removes itself from the fake_units list.
The intent is to provide exception safety when the code
creating the temp unit is unexpectedly forced out of scope.
*/
class fake_unit : public unit {
public:
explicit fake_unit(unit const & u) : unit(u), my_display_(NULL) {}
fake_unit(fake_unit const & u) : unit(u), my_display_(NULL) {}
fake_unit(const unit_type& t, int side, unit_race::GENDER gender = unit_race::NUM_GENDERS)
: unit(t, side, false, gender)
, my_display_(NULL)
{}
/// Assignment operator, taking a fake_unit.
/// If already in the queue, @a this will be moved to the end of the
/// queue (drawn last). The queue (if any) of the parameter is ignored.
fake_unit & operator=(fake_unit const & u)
{ return operator=(static_cast<unit const &>(u)); }
/// Assignment operator, taking a unit.
virtual fake_unit & operator=(unit const & u);
/// Removes @a this from the fake_units_ list if necessary.
~fake_unit();
/// Place @a this on @a display's fake_units_ dequeue.
void place_on_game_display(game_display * d);
/// Removes @a this from whatever fake_units_ list it is on (if any).
int remove_from_game_display();
private :
game_display * my_display_;
};
//Anticipate making place_temporary_unit and remove_temporary_unit private to force exception safety
friend class game_display::fake_unit;
private:
/** Temporarily place a unit on map (moving: can overlap others).
* The temp unit is added at the end of the temporary unit dequeue,
* and therefore gets drawn last, over other units and temp units.
* Adding the same unit twice isn't allowed.
*/
void place_temporary_unit(unit *u);
/** Removes any instances of this temporary unit from the temporary unit vector.
* Returns the number of temp units deleted (0 or 1, any other number indicates an error).
*/
int remove_temporary_unit(unit *u);
public:
/** Set the attack direction indicator. */
void set_attack_indicator(const map_location& src, const map_location& dst);
void clear_attack_indicator();
/** Function to get attack direction suffix. */
std::string attack_indicator_direction() const {
return map_location::write_direction(
attack_indicator_src_.get_relative_dir(attack_indicator_dst_));
}
// Functions used in the editor:
//void draw_terrain_palette(int x, int y, terrain_type::TERRAIN selected);
t_translation::t_terrain get_terrain_on(int palx, int paly, int x, int y);
void send_notification(const std::string& owner, const std::string& message);
/**
* Sets the team controlled by the player using the computer.
*
* Data from this team will be displayed in the game status.
* set_playing_team sets the team whose turn it currently is
*/
void set_team(size_t team, bool observe=false);
void set_playing_team(size_t team);
const map_location &displayed_unit_hex() const { return displayedUnitHex_; }
/**
* annotate hex with number, useful for debugging or UI prototype
*/
static int& debug_highlight(const map_location& loc);
static void clear_debug_highlights() { debugHighlights_.clear(); }
/** The playing team is the team whose turn it is. */
int playing_side() const { return activeTeam_ + 1; }
std::string current_team_name() const;
void add_observer(const std::string& name) { observers_.insert(name); }
void remove_observer(const std::string& name) { observers_.erase(name); }
const std::set<std::string>& observers() const { return observers_; }
void add_chat_message(const time_t& time, const std::string& speaker,
int side, const std::string& msg, events::chat_handler::MESSAGE_TYPE type, bool bell);
void clear_chat_messages() { prune_chat_messages(true); }
void begin_game();
virtual bool in_game() const { return in_game_; }
/**
* Sets the linger mode for the display.
* There have been some discussions on what to do with fog and shroud
* the extra variables make it easier to modify the behavior. There
* might even be a split between victory and defeat.
*
* @todo if the current implementation is wanted we can change
* the stuff back to a boolean
*/
enum tgame_mode {
RUNNING, /**< no linger overlay, show fog and shroud. */
LINGER_SP, /**< linger overlay, show fog and shroud. */
LINGER_MP }; /**< linger overlay, show fog and shroud. */
void set_game_mode(const tgame_mode game_mode);
private:
game_display(const game_display&);
void operator=(const game_display&);
void draw_sidebar();
overlay_map overlay_map_;
/// collection of units destined to be drawn but not put into the unit map
std::deque<unit*> fake_units_;
// Locations of the attack direction indicator's parts
map_location attack_indicator_src_;
map_location attack_indicator_dst_;
pathfind::marked_route route_;
const tod_manager& tod_manager_;
const config& level_;
void invalidate_route();
map_location displayedUnitHex_;
double sidebarScaling_;
bool first_turn_, in_game_;
std::set<std::string> observers_;
struct chat_message
{
chat_message(int speaker, int h) : speaker_handle(speaker), handle(h), created_at(SDL_GetTicks())
{}
int speaker_handle;
int handle;
Uint32 created_at;
};
void prune_chat_messages(bool remove_all=false);
std::vector<chat_message> chat_messages_;
tgame_mode game_mode_;
// For debug mode
static std::map<map_location, int> debugHighlights_;
};
#endif