The Battle for Wesnoth  1.17.23+dev
drawer.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2023
3  by Chris Beck <render787@gmail.com>
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 #include "units/drawer.hpp"
17 
18 #include "color.hpp"
19 #include "display.hpp"
20 #include "display_context.hpp"
21 #include "draw.hpp"
22 #include "formatter.hpp"
23 #include "game_display.hpp"
24 #include "halo.hpp"
25 #include "log.hpp"
26 #include "map/location.hpp"
27 #include "map/map.hpp"
28 #include "picture.hpp"
29 #include "preferences/game.hpp"
30 #include "sdl/surface.hpp"
31 #include "team.hpp"
32 #include "units/animation.hpp"
34 #include "units/frame.hpp"
35 #include "units/types.hpp"
36 #include "units/unit.hpp"
37 
38 static lg::log_domain log_display("display");
39 #define LOG_DP LOG_STREAM(info, log_display)
40 
41 namespace
42 {
43 /**
44  * Wrapper which will assemble the image path (including IPF for the color from get_orb_color) for a given orb.
45  * Returns nullptr if the preferences have been configured to hide this orb.
46  */
47 std::unique_ptr<image::locator> get_orb_image(orb_status os)
48 {
49  if(os == orb_status::disengaged) {
53  return std::make_unique<image::locator>(game_config::images::orb_two_color + "~RC(ellipse_red>"
54  + moved_color + ")~RC(magenta>" + partial_color + ")");
55  }
57  }
58 
60  return nullptr;
61  auto color = orb_status_helper::get_orb_color(os);
62  return std::make_unique<image::locator>(game_config::images::orb + "~RC(magenta>" + color + ")");
63 }
64 
65 /**
66  * Assemble a two-color orb for an ally's unit, during that ally's turn.
67  * Returns nullptr if the preferences both of these orbs and ally orbs in general are off.
68  * Returns a one-color orb (using the ally color) in several circumstances.
69  */
70 std::unique_ptr<image::locator> get_playing_ally_orb_image(orb_status os)
71 {
73  return get_orb_image(orb_status::allied);
74 
75  // This is conditional on prefs_show_orb, because a user might want to disable the standard
76  // partial orb, but keep it enabled as a reminder for units in the disengaged state.
79  }
80 
82  return get_orb_image(orb_status::allied);
83 
85  auto status_color = orb_status_helper::get_orb_color(os);
86  return std::make_unique<image::locator>(game_config::images::orb_two_color + "~RC(ellipse_red>"
87  + allied_color + ")~RC(magenta>" + status_color + ")");
88 }
89 
90 void draw_bar(int xpos, int ypos, int bar_height, double filled, const color_t& col)
91 {
92  // Magic width number
93  static constexpr unsigned int bar_width = 4;
94 
95  static constexpr color_t bar_color_bg{0, 0, 0, 80};
96  static constexpr color_t bar_color_border{213, 213, 213, 200};
97 
98  // We used to use an image for the bar instead of drawing it procedurally. Its x,y position
99  // within the file was 19,13, so we offset the origin by that much to make it line up with
100  // the crowns as before. Should probably compensate for this better in the future.
101  const point offset = display::scaled_to_zoom(point{19, 13});
102 
103  // Full bar dimensions.
104  rect bar_rect = display::scaled_to_zoom({
105  xpos + offset.x,
106  ypos + offset.y,
107  bar_width,
108  bar_height
109  });
110 
111  // Bar dimensions should not overflow 80% of the scaled hex dimensions.
112  // The 80% comes from an approximation of the length of a segment drawn
113  // inside a regular hexagon that runs parallel to its outer left side.
114  bar_rect.w = std::clamp<int>(bar_rect.w, 0, display::hex_size() * 0.80 - offset.x);
115  bar_rect.h = std::clamp<int>(bar_rect.h, 0, display::hex_size() * 0.80 - offset.y);
116 
117  filled = std::clamp<double>(filled, 0.0, 1.0);
118  const int unfilled = static_cast<std::size_t>(bar_rect.h * (1.0 - filled));
119 
120  // Filled area dimensions.
121  const rect fill_rect {
122  bar_rect.x,
123  bar_rect.y + unfilled,
124  bar_rect.w,
125  bar_rect.h - unfilled
126  };
127 
128  // Tinted background.
129  draw::fill(bar_rect, bar_color_bg);
130 
131  // Filled area.
132  draw::fill(fill_rect, col);
133 
134  // Bar outline.
135  draw::rect(bar_rect, bar_color_border);
136 }
137 }
138 
140  : disp(thedisp)
141  , dc(disp.get_disp_context())
142  , map(dc.map())
143  , teams(dc.teams())
144  , halo_man(thedisp.get_halo_manager())
145  , viewing_team(disp.viewing_team())
146  , playing_team(disp.playing_team())
147  , viewing_team_ref(teams[viewing_team])
148  , playing_team_ref(teams[playing_team])
149  , is_blindfolded(disp.is_blindfolded())
150  , show_everything(disp.show_everything())
151  , sel_hex(disp.selected_hex())
152  , mouse_hex(disp.mouseover_hex())
153  , zoom_factor(disp.get_zoom_factor())
154  , hex_size(disp.hex_size())
155  , hex_size_by_2(disp.hex_size() / 2)
156 {
157  if(const game_display* game_display = dynamic_cast<class game_display*>(&disp)) {
159  }
160 
161  // This used to be checked in the drawing code, where it simply triggered skipping some logic.
162  // However, I think it's obsolete, and that the initialization of viewing_team_ref would already
163  // be undefined behavior in the situation where this assert fails.
164  assert(disp.team_valid());
165 }
166 
167 void unit_drawer::redraw_unit(const unit& u) const
168 {
170  map_location loc = u.get_location();
171 
172  int side = u.side();
173 
174  bool hidden = u.get_hidden();
175  bool is_flying = u.is_flying();
176  map_location::DIRECTION facing = u.facing();
177  int hitpoints = u.hitpoints();
178  int max_hitpoints = u.max_hitpoints();
179 
180  bool can_recruit = u.can_recruit();
181  bool can_advance = u.can_advance();
182 
183  int experience = u.experience();
184  int max_experience = u.max_experience();
185 
186  bool emit_zoc = u.emits_zoc();
187 
188  color_t hp_color=u.hp_color();
189  color_t xp_color=u.xp_color();
190 
191  std::string ellipse=u.image_ellipse();
192 
193  const bool is_highlighted_enemy = units_that_can_reach_goal.count(loc) > 0;
194  const bool is_selected_hex = (loc == sel_hex || is_highlighted_enemy);
195 
196  // Override the filled area's color's alpha.
197  hp_color.a = (loc == mouse_hex || is_selected_hex) ? 255u : float_to_color(0.8);
198  xp_color.a = hp_color.a;
199 
201  ac.clear_haloes();
202  if(ac.anim_) {
203  ac.anim_->update_last_draw_time();
204  }
205  return;
206  }
207 
208  if (!ac.anim_) {
209  ac.set_standing();
210  if (!ac.anim_) return;
211  }
212 
213  if (ac.refreshing_) return;
214  ac.refreshing_ = true;
215 
216  ac.anim_->update_last_draw_time();
217  frame_parameters params;
218  const t_translation::terrain_code terrain = map.get_terrain(loc);
219  const terrain_type& terrain_info = map.get_terrain_info(terrain);
220 
221  // do not set to 0 so we can distinguish the flying from the "not on submerge terrain"
222  // instead use -1.0 (as in "negative depth", it will be ignored by rendering)
223  params.submerge= is_flying ? -1.0 : terrain_info.unit_submerge();
224 
225  if(u.invisible(loc) && params.highlight_ratio > 0.6) {
226  params.highlight_ratio = 0.6;
227  }
228  if (is_selected_hex && params.highlight_ratio == 1.0) {
229  params.highlight_ratio = 1.5;
230  }
231 
232  int height_adjust = static_cast<int>(terrain_info.unit_height_adjust() * zoom_factor);
233  if (is_flying && height_adjust < 0) {
234  height_adjust = 0;
235  }
236  params.y -= height_adjust;
237  params.halo_y -= height_adjust;
238 
239  int red = 0,green = 0,blue = 0,tints = 0;
240  double blend_ratio = 0;
241  // Add future colored states here
242  if(u.poisoned()) {
243  green += 255;
244  blend_ratio += 0.25;
245  tints += 1;
246  }
247  if(u.slowed()) {
248  red += 191;
249  green += 191;
250  blue += 255;
251  blend_ratio += 0.25;
252  tints += 1;
253  }
254  if(tints > 0) {
255  params.blend_with = color_t((red/tints),(green/tints),(blue/tints));
256  params.blend_ratio = ((blend_ratio/tints));
257  }
258 
259  //hackish : see unit_frame::merge_parameters
260  // we use image_mod on the primary image
261  // and halo_mod on secondary images and all haloes
262  params.image_mod = u.image_mods();
263  params.halo_mod = u.TC_image_mods();
264  params.image= u.default_anim_image();
265 
266 
267  if(u.incapacitated()) params.image_mod +="~GS()";
268  params.primary_frame = true;
269 
270 
271  const frame_parameters adjusted_params = ac.anim_->get_current_params(params);
272 
273  const map_location dst = loc.get_direction(facing);
274  const int xsrc = disp.get_location_x(loc);
275  const int ysrc = disp.get_location_y(loc);
276  const int xdst = disp.get_location_x(dst);
277  const int ydst = disp.get_location_y(dst);
278 
279  // We draw bars only if wanted, visible on the map view
280  bool draw_bars = ac.draw_bars_ ;
281  if (draw_bars) {
282  rect unit_rect {xsrc, ysrc +adjusted_params.y, hex_size, hex_size};
283  draw_bars = unit_rect.overlaps(disp.map_outside_area());
284  }
285 
286  texture ellipse_front;
287  texture ellipse_back;
288  int ellipse_floating = 0;
289  // Always show the ellipse for selected units
290  if(draw_bars && (preferences::show_side_colors() || is_selected_hex)) {
291  if(adjusted_params.submerge > 0.0) {
292  // The division by 2 seems to have no real meaning,
293  // It just works fine with the current center of ellipse
294  // and prevent a too large adjust if submerge = 1.0
295  ellipse_floating = static_cast<int>(adjusted_params.submerge * hex_size_by_2);
296  }
297 
298  if(ellipse.empty()){
299  ellipse="misc/ellipse";
300  }
301 
302  if(ellipse != "none") {
303  // check if the unit has a ZoC or can recruit
304  const std::string nozoc = !emit_zoc ? "nozoc-" : "";
305  const std::string leader = can_recruit ? "leader-" : "";
306  const std::string selected = is_selected_hex? "selected-" : "";
307  const std::string tc = team::get_side_color_id(side);
308 
309  const std::string ellipse_top = formatter() << ellipse << "-" << leader << nozoc << selected << "top.png~RC(ellipse_red>" << tc << ")";
310  const std::string ellipse_bot = formatter() << ellipse << "-" << leader << nozoc << selected << "bottom.png~RC(ellipse_red>" << tc << ")";
311 
312  // Load the ellipse parts recolored to match team color
313  ellipse_back = image::get_texture(image::locator(ellipse_top));
314  ellipse_front = image::get_texture(image::locator(ellipse_bot));
315  }
316  }
317 
318  disp.drawing_buffer_add(display::LAYER_UNIT_FIRST, loc, [=, adj_y = adjusted_params.y](const rect& d) {
319  // Both front and back have the same origin
320  const point origin { d.x, d.y + adj_y - ellipse_floating };
321 
322  if(ellipse_back) {
323  draw::blit(ellipse_back, display::scaled_to_zoom({origin.x, origin.y, ellipse_back.w(), ellipse_back.h()}));
324  }
325 
326  if(ellipse_front) {
327  draw::blit(ellipse_front, display::scaled_to_zoom({origin.x, origin.y, ellipse_front.w(), ellipse_front.h()}));
328  }
329  });
330 
331  if(draw_bars) {
332  const auto& type_cfg = u.type().get_cfg();
333  const auto& cfg_offset_x = type_cfg["bar_offset_x"];
334  const auto& cfg_offset_y = type_cfg["bar_offset_y"];
335  int xoff;
336  int yoff;
337  if(cfg_offset_x.empty() && cfg_offset_y.empty()) {
339  image::get_size(u.default_anim_image())
340  );
341  xoff = !s.x ? 0 : (hex_size - s.x)/2;
342  yoff = !s.y ? 0 : (hex_size - s.x)/2;
343  }
344  else {
345  xoff = cfg_offset_x.to_int();
346  yoff = cfg_offset_y.to_int();
347  }
348 
349  using namespace orb_status_helper;
350  std::unique_ptr<image::locator> orb_img = nullptr;
351 
352  if(viewing_team_ref.is_enemy(side)) {
353  if(!u.incapacitated())
354  orb_img = get_orb_image(orb_status::enemy);
355  } else if(static_cast<std::size_t>(side) != playing_team + 1) {
356  // We're looking at either the player's own unit or an ally's unit, but either way it
357  // doesn't belong to the playing_team and isn't expected to move until after its next
358  // turn refresh.
359  auto os = orb_status::moved;
360  if(static_cast<std::size_t>(side) != viewing_team + 1)
361  os = orb_status::allied;
362  orb_img = get_orb_image(os);
363  } else if(static_cast<std::size_t>(side) != viewing_team + 1) {
364  // We're looking at an ally's unit, during that ally's turn.
365  auto os = dc.unit_orb_status(u);
366  orb_img = get_playing_ally_orb_image(os);
367  } else {
368  // We're looking at the player's own unit, during the player's turn.
369  auto os = dc.unit_orb_status(u);
370  orb_img = get_orb_image(os);
371  }
372 
373  // All the various overlay textures to draw with the HP/XP bars
374  std::vector<texture> textures;
375 
376  if(orb_img != nullptr) {
377  textures.push_back(image::get_texture(*orb_img));
378  }
379 
380  if(can_recruit) {
381  if(texture tex = image::get_texture(u.leader_crown())) {
382  textures.push_back(std::move(tex));
383  }
384  }
385 
386  for(const std::string& ov : u.overlays()) {
387  if(texture tex = image::get_texture(ov)) {
388  textures.push_back(std::move(tex));
389  }
390  };
391 
392  const std::vector<std::string> overlays_abilities = u.overlays_abilities();
393  for(const std::string& ov : overlays_abilities) {
394  if(texture tex = image::get_texture(ov)) {
395  textures.push_back(std::move(tex));
396  }
397  };
398 
399  disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, [=,
400  textures = std::move(textures),
401  adj_y = adjusted_params.y,
402  //origin = point{xsrc + xoff, ysrc + yoff + adjusted_params.y},
403  bar_hp_height = static_cast<int>(max_hitpoints * u.hp_bar_scaling()),
404  bar_xp_height = static_cast<int>(max_experience * u.xp_bar_scaling() / std::max<int>(u.level(), 1))
405  ](const rect& d) {
406  const point origin { d.x + xoff, d.y + yoff + adj_y };
407 
408  for(const texture& tex : textures) {
409  draw::blit(tex, display::scaled_to_zoom({origin.x, origin.y, tex.w(), tex.h()}));
410  }
411 
412  if(max_hitpoints > 0) {
413  // Offset slightly to make room for the XP bar
414  const int hp_offset = static_cast<int>(-5 * display::get_zoom_factor());
415 
416  double filled = static_cast<double>(hitpoints) / static_cast<double>(max_hitpoints);
417  draw_bar(origin.x + hp_offset, origin.y, bar_hp_height, filled, hp_color);
418  }
419 
420  if(experience > 0 && can_advance) {
421  double filled = static_cast<double>(experience) / static_cast<double>(max_experience);
422  draw_bar(origin.x, origin.y, bar_xp_height, filled, xp_color);
423  }
424  });
425  }
426 
427  // Smooth unit movements from terrain of different elevation.
428  // Do this separately from above so that the health bar doesn't go up and down.
429 
430  const t_translation::terrain_code terrain_dst = map.get_terrain(dst);
431  const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst);
432 
433  // height_adjust_unit is not scaled by zoom_factor here otherwise it results in a squared offset that results in #5974
434  // It appears the tiles and units are scaled together somewhere else
435  int height_adjust_unit = static_cast<int>(terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) +
436  terrain_dst_info.unit_height_adjust() * adjusted_params.offset);
437  if (is_flying && height_adjust_unit < 0) {
438  height_adjust_unit = 0;
439  }
440  params.y -= height_adjust_unit - height_adjust;
441  params.halo_y -= height_adjust_unit - height_adjust;
442  // TODO: params.halo_y is not used. Why is it set?
443 
444  const int halo_x =
445  static_cast<int>(
446  adjusted_params.offset * xdst
447  + (1.0 - adjusted_params.offset) * xsrc
448  )
449  + hex_size_by_2;
450  const int halo_y =
451  static_cast<int>(
452  adjusted_params.offset * ydst
453  + (1.0 - adjusted_params.offset) * ysrc
454  )
455  + hex_size_by_2 - height_adjust_unit * zoom_factor;
456 
457  bool has_halo = ac.unit_halo_ && ac.unit_halo_->valid();
458  if(!has_halo && !u.image_halo().empty()) {
459  ac.unit_halo_ = halo_man.add(
460  halo_x, halo_y,
461  u.image_halo() + u.TC_image_mods(),
462  map_location(-1, -1)
463  );
464  }
465  if(has_halo && u.image_halo().empty()) {
466  halo_man.remove(ac.unit_halo_);
467  ac.unit_halo_.reset();
468  } else if(has_halo) {
469  halo_man.set_location(ac.unit_halo_, halo_x, halo_y);
470  }
471 
472  const std::vector<std::string> halos_abilities = u.halo_abilities();
473  bool has_abil_halo = !ac.abil_halos_.empty() && ac.abil_halos_.front()->valid();
474  if(!has_abil_halo && !halos_abilities.empty()) {
475  for(const std::string& halo_ab : halos_abilities){
476  halo::handle abil_halo = halo_man.add(
477  halo_x, halo_y,
478  halo_ab + u.TC_image_mods(),
479  map_location(-1, -1)
480  );
481  if(abil_halo->valid()){
482  ac.abil_halos_.push_back(abil_halo);
483  }
484  }
485  }
486  if(has_abil_halo && (ac.abil_halos_ref_ != halos_abilities || halos_abilities.empty())){
487  for(halo::handle& abil_halo : ac.abil_halos_){
488  halo_man.remove(abil_halo);
489  }
490  ac.abil_halos_.clear();
491  if(!halos_abilities.empty()){
492  for(const std::string& halo_ab : halos_abilities){
493  halo::handle abil_halo = halo_man.add(
494  halo_x, halo_y,
495  halo_ab + u.TC_image_mods(),
496  map_location(-1, -1)
497  );
498  if(abil_halo->valid()){
499  ac.abil_halos_.push_back(abil_halo);
500  }
501  }
502  }
503  } else if(has_abil_halo){
504  for(halo::handle& abil_halo : ac.abil_halos_){
505  halo_man.set_location(abil_halo, halo_x, halo_y);
506  }
507  }
508 
509  ac.abil_halos_ref_ = halos_abilities;
510 
511  ac.anim_->redraw(params, halo_man);
512  ac.refreshing_ = false;
513 }
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:87
@ LAYER_UNIT_FIRST
Reserve layers to be selected for WML.
Definition: display.hpp:817
@ LAYER_UNIT_BAR
Unit bars and overlays are drawn on this layer (for testing here).
Definition: display.hpp:842
static int hex_size()
Function which returns the size of a hex in pixels (from top tip to bottom tip or left edge to right ...
Definition: display.hpp:264
int get_location_x(const map_location &loc) const
Functions to get the on-screen positions of hexes.
Definition: display.cpp:712
static double get_zoom_factor()
Returns the current zoom factor.
Definition: display.hpp:267
void drawing_buffer_add(const drawing_layer layer, const map_location &loc, decltype(draw_helper::do_draw) draw_func)
Add an item to the drawing buffer.
Definition: display.cpp:1288
rect map_outside_area() const
Returns the available area for a map, this may differ from the above.
Definition: display.cpp:545
bool team_valid() const
Definition: display.cpp:697
int get_location_y(const map_location &loc) const
Definition: display.cpp:717
static rect scaled_to_zoom(const SDL_Rect &r)
Scale the width and height of a rect by the current zoom factor.
Definition: display.hpp:273
std::ostringstream wrapper.
Definition: formatter.hpp:40
const std::set< map_location > & units_that_can_reach_goal() const
Return the locations of units that can reach goal (.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
Definition: map.cpp:302
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:98
Generic locator abstracting the location of an image.
Definition: picture.hpp:64
static std::string get_side_color_id(unsigned side)
Definition: team.cpp:972
int unit_height_adjust() const
Definition: terrain.hpp:137
double unit_submerge() const
Definition: terrain.hpp:138
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition: texture.hpp:33
bool draw_bars_
bool indicating whether to draw bars with the unit
std::unique_ptr< unit_animation > anim_
The current animation.
void set_standing(bool with_bars=true)
Sets the animation state to standing.
bool refreshing_
avoid infinite recursion.
void clear_haloes()
Clear the haloes associated to the unit.
const team & viewing_team_ref
Definition: drawer.hpp:59
const gamemap & map
Definition: drawer.hpp:54
double zoom_factor
Definition: drawer.hpp:65
void redraw_unit(const unit &u) const
draw a unit.
Definition: drawer.cpp:167
bool show_everything
Definition: drawer.hpp:62
display & disp
Definition: drawer.hpp:52
std::set< map_location > units_that_can_reach_goal
Definition: drawer.hpp:66
int hex_size
Definition: drawer.hpp:68
map_location sel_hex
Definition: drawer.hpp:63
int hex_size_by_2
Definition: drawer.hpp:69
unit_drawer(display &thedisp)
Definition: drawer.cpp:139
map_location mouse_hex
Definition: drawer.hpp:64
bool is_blindfolded
Definition: drawer.hpp:61
This class represents a single unit of a specific type.
Definition: unit.hpp:135
constexpr uint8_t float_to_color(double n)
Convert a double in the range [0.0,1.0] to an 8-bit colour value.
Definition: color.hpp:280
Drawing functions, for drawing things on the screen.
static lg::log_domain log_display("display")
Frame for unit's animation sequence.
bool invisible(const map_location &loc, bool see_all=true) const
Definition: unit.cpp:2598
bool is_visible_to_team(const team &team, bool const see_all=true) const
Definition: unit.cpp:2641
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:507
bool incapacitated() const
Check if the unit has been petrified.
Definition: unit.hpp:907
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:501
bool slowed() const
Check if the unit has been slowed.
Definition: unit.hpp:916
bool get_hidden() const
Gets whether this unit is currently hidden on the map.
Definition: unit.hpp:722
int experience() const
The current number of experience points this unit has.
Definition: unit.hpp:525
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Definition: unit.hpp:614
int side() const
The side this unit belongs to.
Definition: unit.hpp:345
bool poisoned() const
Check if the unit has been poisoned.
Definition: unit.hpp:898
int max_experience() const
The max number of experience points this unit can have.
Definition: unit.hpp:531
bool can_advance() const
Checks whether this unit has any options to advance to.
Definition: unit.hpp:274
color_t xp_color() const
Color for this unit's XP.
Definition: unit.cpp:1153
unit_animation_component & anim_comp() const
Definition: unit.hpp:1546
color_t hp_color() const
Color for this unit's current hitpoints.
Definition: unit.cpp:1099
std::string TC_image_mods() const
Constructs a recolor (RC) IPF string for this unit's team color.
Definition: unit.cpp:2751
std::string image_ellipse() const
Get the unit's ellipse image.
Definition: unit.hpp:1575
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
Definition: unit.cpp:2756
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
Definition: unit.cpp:2580
bool emits_zoc() const
Tests whether the unit has a zone-of-control, considering incapacitated.
Definition: unit.hpp:1340
const map_location & get_location() const
The current map location this unit is at.
Definition: unit.hpp:1359
map_location::DIRECTION facing() const
The current direction this unit is facing within its hex.
Definition: unit.hpp:1375
bool is_flying() const
Check if the unit is a flying unit.
Definition: unit.hpp:1468
Standard logging facilities (interface).
void fill(const SDL_Rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
Definition: draw.cpp:51
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:311
void rect(const SDL_Rect &rect)
Draw a rectangle.
Definition: draw.cpp:151
std::string orb_two_color
std::string selected
std::shared_ptr< halo_record > handle
Definition: halo.hpp:31
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
Definition: picture.cpp:985
point get_size(const locator &i_locator, bool skip_cache)
Returns the width and height of an image.
Definition: picture.cpp:827
std::string get_orb_color(orb_status os)
Wrapper for the various preferences::unmoved_color(), moved_color(), etc methods, using the enum inst...
Definition: orb_status.cpp:40
bool prefs_show_orb(orb_status os)
Wrapper for the various preferences::show_..._orb() methods, using the enum instead of exposing a sep...
Definition: orb_status.cpp:19
std::string moved_color()
Definition: general.cpp:352
std::string partial_color()
Definition: general.cpp:372
bool show_status_on_ally_orb()
Definition: general.cpp:269
std::string allied_color()
Definition: general.cpp:322
bool show_side_colors()
Definition: game.cpp:746
orb_status
Corresponds to the colored orbs displayed above units' hp-bar and xp-bar.
Definition: orb_status.hpp:24
@ partial
There are still moves and/or attacks possible, but the unit doesn't fit in the "unmoved" status.
@ moved
All moves and possible attacks have been done.
@ disengaged
The unit can move but can't attack, and wouldn't be able to attack even if it was moved to a hex adja...
@ allied
Belongs to a friendly side.
@ enemy
Belongs to a non-friendly side; normally visualised by not displaying an orb.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
All parameters from a frame at a given instant.
Definition: frame.hpp:36
double highlight_ratio
Definition: frame.hpp:58
std::string image_mod
Definition: frame.hpp:44
double submerge
Definition: frame.hpp:60
boost::tribool primary_frame
Definition: frame.hpp:69
image::locator image
Definition: frame.hpp:41
double blend_ratio
Definition: frame.hpp:57
std::optional< color_t > blend_with
Definition: frame.hpp:55
std::string halo_mod
Definition: frame.hpp:50
Encapsulates the map of the game.
Definition: location.hpp:38
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:40
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
Definition: location.cpp:360
Holds a 2D point.
Definition: point.hpp:25
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:49
static map_location::DIRECTION s
#define d