The Battle for Wesnoth  1.17.10+dev
attack.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2022
3  by Gabriel Morin <gabrielmorin (at) gmail (dot) 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 /**
17  * @file
18  */
19 
20 #include "whiteboard/attack.hpp"
21 
22 #include "whiteboard/visitor.hpp"
23 #include "whiteboard/utility.hpp"
24 
25 #include "arrow.hpp"
26 #include "config.hpp"
27 #include "draw.hpp"
28 #include "fake_unit_ptr.hpp"
29 #include "game_board.hpp"
30 #include "play_controller.hpp"
31 #include "resources.hpp"
32 #include "units/unit.hpp"
33 #include "units/map.hpp"
34 
35 namespace wb
36 {
37 
38 std::ostream &operator<<(std::ostream &s, attack_ptr attack)
39 {
40  assert(attack);
41  return attack->print(s);
42 }
43 
44 std::ostream &operator<<(std::ostream &s, attack_const_ptr attack)
45 {
46  assert(attack);
47  return attack->print(s);
48 }
49 
50 std::ostream& attack::print(std::ostream& s) const
51 {
52  s << "Attack on (" << get_target_hex() << ") preceded by ";
53  move::print(s);
54  return s;
55 }
56 
57 attack::attack(std::size_t team_index, bool hidden, unit& u, const map_location& target_hex, int weapon_choice, const pathfind::marked_route& route,
58  arrow_ptr arrow, fake_unit_ptr fake_unit)
59  : move(team_index, hidden, u, route, arrow, std::move(fake_unit)),
60  target_hex_(target_hex),
61  weapon_choice_(weapon_choice),
62  attack_movement_cost_(u.attacks()[weapon_choice_].movement_used()),
64 {
65  this->init();
66 }
67 
68 attack::attack(const config& cfg, bool hidden)
69  : move(cfg,hidden)
70  , target_hex_(cfg.child("target_hex_")["x"],cfg.child("target_hex_")["y"], wml_loc())
71  , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1
74 {
75  // Validate target_hex
77  throw action::ctor_err("attack: Invalid target_hex_");
78 
79  // Validate weapon_choice_
80  if(weapon_choice_ < 0 || weapon_choice_ >= static_cast<int>(get_unit()->attacks().size()))
81  throw action::ctor_err("attack: Invalid weapon_choice_");
82 
83  // Construct attack_movement_cost_
84  assert(get_unit());
85  attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used();
86 
87  this->init();
88 }
89 
91 {
93 }
94 
96 {
97  invalidate();
98 }
99 
101 {
102  v.visit(shared_from_this());
103 }
104 
105 /* private */
107 {
109  {
110  //invalidate dest and target hex so attack indicator is properly cleared
113  }
114 }
115 
116 void attack::execute(bool& success, bool& complete)
117 {
118  if(!valid()) {
119  success = false;
120  //Setting complete to true signifies to side_actions to delete the planned action: nothing more to do with it.
121  complete = true;
122  return;
123  }
124 
125  LOG_WB << "Executing: " << shared_from_this();
126 
127  if (route_->steps.size() >= 2)
128  {
129  bool m_success, m_complete;
130  move::execute(m_success,m_complete);
131  if(!m_success) {
132  //Move failed for some reason, so don't attack.
133  success = false;
134  complete = true;
135  return;
136  }
137  }
138 
140  complete = true;
141 
142  //check that attacking unit is still alive, if not, consider the attack a failure
144  if(!survivor.valid() || (!unit_id_.empty() && (survivor->id() != unit_id_)))
145  {
146  success = false;
147  }
148 
149  success = true;
150 }
151 
153 {
154  move::apply_temp_modifier(unit_map);
155  assert(get_unit());
156  unit& unit = *get_unit();
157  DBG_WB << unit.name() << " [" << unit.id()
158  << "] has " << unit.attacks_left() << " attacks, decreasing by one";
159  assert(unit.attacks_left() > 0);
160  unit.set_attacks(unit.attacks_left() - 1);
161 
162  //Calculate movement to subtract
164  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
165  << "] from " << unit.movement_left() << " to "
166  << unit.movement_left() - temp_movement_subtracted_ << ".";
168 
169  //Update status of fake unit (not undone by remove_temp_modifiers)
170  //@todo this contradicts the name "temp_modifiers"
171  if (fake_unit_) { //Attacks that are not attack-moves don't have fake units
172  fake_unit_->set_movement(unit.movement_left(), true);
173  fake_unit_->set_attacks(unit.attacks_left());
174  }
175 }
176 
178 {
179  assert(get_unit());
180  unit& unit = *get_unit();
181  DBG_WB << unit.name() << " [" << unit.id()
182  << "] has " << unit.attacks_left() << " attacks, increasing by one";
183  unit.set_attacks(unit.attacks_left() + 1);
184  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
185  << "] from " << unit.movement_left() << " to "
186  << unit.movement_left() + temp_movement_subtracted_ << ".";
189  move::remove_temp_modifier(unit_map);
190 }
191 
192 // Draws the attack indicator.
194 {
195  if (hex != get_dest_hex() && hex != target_hex_) {
196  return;
197  }
198 
199  //@todo: replace this by either the use of transparency + LAYER_ATTACK_INDICATOR,
200  //or a dedicated layer
202 
203  //calculate direction (valid for both hexes)
204  std::string direction_text = map_location::write_direction(
205  get_dest_hex().get_relative_dir(target_hex_));
206 
207  if (hex == get_dest_hex()) //add symbol to attacker hex
208  {
209  auto disp = display::get_singleton();
210 
211  disp->drawing_buffer_add(layer, get_dest_hex(),
212  [=, tex = image::get_texture("whiteboard/attack-indicator-src-" + direction_text + ".png", image::HEXED)](const rect& d) {
213  draw::blit(tex, disp->scaled_to_zoom({d.x, d.y, tex.w(), tex.h()}));
214  });
215  }
216  else if (hex == target_hex_) //add symbol to defender hex
217  {
218  auto disp = display::get_singleton();
219 
220  disp->drawing_buffer_add(layer, target_hex_,
221  [=, tex = image::get_texture("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::HEXED)](const rect& d) {
222  draw::blit(tex, disp->scaled_to_zoom({d.x, d.y, tex.w(), tex.h()}));
223  });
224  }
225 }
226 
228 {
229  move::redraw();
231 }
232 
234 {
235  // Verify that the unit that planned this attack exists
236  if(!get_unit()) {
237  return NO_UNIT;
238  }
239  // Verify that the target hex is still valid
240  if(!target_hex_.valid()) {
241  return INVALID_LOCATION;
242  }
243  // Verify that the target hex isn't empty
245  return NO_TARGET;
246  }
247  // Verify that the attacking unit has attacks left
248  if(get_unit()->attacks_left() <= 0) {
249  return NO_ATTACK_LEFT;
250  }
251  // Verify that the attacker and target are enemies
252  if(!resources::gameboard->get_team(get_unit()->side()).is_enemy(resources::gameboard->units().find(target_hex_)->side())){
253  return NOT_AN_ENEMY;
254  }
255  //@todo: (maybe) verify that the target hex contains the same unit that before,
256  // comparing for example the unit ID
257 
258  return move::check_validity();
259 }
260 
262 {
263  config final_cfg = move::to_config();
264 
265  final_cfg["type"] = "attack";
266  final_cfg["weapon_choice_"] = weapon_choice_;
267 // final_cfg["attack_movement_cost_"] = attack_movement_cost_; //Unnecessary
268 // final_cfg["temp_movement_subtracted_"] = temp_movement_subtracted_; //Unnecessary
269 
270  config target_hex_cfg;
271  target_hex_cfg["x"]=target_hex_.wml_x();
272  target_hex_cfg["y"]=target_hex_.wml_y();
273  final_cfg.add_child("target_hex_", std::move(target_hex_cfg));
274 
275  return final_cfg;
276 }
277 
278 } // end namespace wb
Drawing functions, for drawing things on the screen.
map_location target_hex_
the target of the attack
Definition: attack.hpp:80
play_controller * controller
Definition: resources.cpp:22
std::string unit_id_
Definition: move.hpp:111
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition: unit.hpp:995
void set_movement(int moves, bool unit_action=false)
Set this unit&#39;s remaining movement to moves.
Definition: unit.cpp:1181
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition: attack.cpp:152
virtual void execute(bool &success, bool &complete)
Output parameters: success: Whether or not to continue an execute-all after this execution complete: ...
Definition: attack.cpp:116
Arrows destined to be drawn on the map.
unit_iterator end()
Definition: map.hpp:429
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:98
virtual const unit_map & units() const override
Definition: game_board.hpp:113
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3141
int weapon_choice_
Definition: attack.hpp:82
This class represents a single unit of a specific type.
Definition: unit.hpp:133
attack(std::size_t team_index, bool hidden, unit &mover, const map_location &target_hex, int weapon_choice, const pathfind::marked_route &route, arrow_ptr arrow, fake_unit_ptr fake_unit)
Definition: attack.cpp:57
int attack_movement_cost_
Definition: attack.hpp:83
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: attack.cpp:227
std::shared_ptr< attack > attack_ptr
Definition: typedefs.hpp:70
virtual std::ostream & print(std::ostream &s) const
Definition: move.cpp:59
int wml_x() const
Definition: location.hpp:153
virtual void visit(move_ptr move)=0
STL namespace.
int temp_movement_subtracted_
Definition: attack.hpp:84
#define d
std::shared_ptr< attack const > attack_const_ptr
Definition: typedefs.hpp:71
Standard hexagonal tile mask applied, removing portions that don&#39;t fit.
Definition: picture.hpp:233
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: move.cpp:374
std::shared_ptr< attack > shared_from_this()
Definition: attack.hpp:65
drawing_layer
The layers to render something on.
Definition: display.hpp:792
Definitions for the interface to Wesnoth Markup Language (WML).
virtual error check_validity() const
Check the validity of the action.
Definition: attack.cpp:233
std::size_t team_index() const
Returns the index of the team that owns this action.
Definition: action.hpp:84
virtual void execute(bool &success, bool &complete)
Output parameters: success: Whether or not to continue an execute-all after this execution complete: ...
Definition: move.cpp:207
virtual ~attack()
Definition: attack.cpp:95
bool valid()
Returns whether this action is valid or not.
Definition: action.hpp:135
virtual void accept(visitor &v)
Definition: attack.cpp:100
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:87
const std::string & id() const
Gets this unit&#39;s id.
Definition: unit.hpp:383
Arrows destined to be drawn on the map.
Definition: arrow.hpp:30
virtual map_location get_dest_hex() const
Definition: move.cpp:305
error
Possible errors.
Definition: action.hpp:106
fake_unit_ptr fake_unit_
Definition: move.hpp:118
int wml_y() const
Definition: location.hpp:154
bool valid() const
Definition: location.hpp:89
game_board * gameboard
Definition: resources.cpp:21
virtual error check_validity() const
Check the validity of the action.
Definition: move.cpp:441
const t_string & name() const
Gets this unit&#39;s translatable display name.
Definition: unit.hpp:406
virtual unit_ptr get_unit() const
Return the unit targeted by this action.
Definition: move.cpp:290
Structure which holds a single route and marks for special events.
Definition: pathfind.hpp:141
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition: move.cpp:336
void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: move.cpp:568
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: attack.cpp:261
Encapsulates the map of the game.
Definition: location.hpp:38
unit_iterator find(std::size_t id)
Definition: map.cpp:301
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: attack.cpp:177
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:503
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: move.cpp:507
void set_attacks(int left)
Sets the number of attacks this unit has left this turn.
Definition: unit.hpp:1016
void attack_enemy(const map_location &attacker_loc, const map_location &defender_loc, int choice)
static map_location::DIRECTION s
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
const map_location & get_target_hex() const
Definition: attack.hpp:59
#define LOG_WB
Definition: typedefs.hpp:27
config & add_child(config_key_type key)
Definition: config.cpp:514
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition: draw.cpp:301
std::shared_ptr< arrow > arrow_ptr
Definition: typedefs.hpp:60
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
bool hidden() const
Definition: action.hpp:64
#define DBG_WB
Definition: typedefs.hpp:28
Container associating units to locations.
Definition: map.hpp:98
std::ostream & operator<<(std::ostream &s, action_ptr action)
Definition: action.cpp:34
virtual std::ostream & print(std::ostream &s) const
Definition: attack.cpp:50
visitor is an abstract interface : action.accept(visitor) calls visitor.visit(action) ...
std::unique_ptr< pathfind::marked_route > route_
Definition: move.hpp:112
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:60
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:1128
bool valid() const
Definition: map.hpp:274
virtual void draw_hex(const map_location &hex)
Gets called by display when drawing a hex, to allow actions to draw to the screen.
Definition: attack.cpp:193
void invalidate()
invalidates the move-destination and attack-target hexes
Definition: attack.cpp:106
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:141
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition: unit.hpp:1283
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex...
Definition: move.hpp:35
Definition: display.hpp:49
Footsteps showing path from unit to mouse.
Definition: display.hpp:799
void init()
Definition: attack.cpp:90
Abstract base class for all the visitors (cf GoF Visitor Design Pattern) the whiteboard uses...
Definition: visitor.hpp:32