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