The Battle for Wesnoth  1.15.1+dev
attack.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2018 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13  */
14 
15 /**
16  * @file
17  */
18 
19 #include "whiteboard/attack.hpp"
20 
21 #include "whiteboard/visitor.hpp"
22 #include "whiteboard/utility.hpp"
23 
24 #include "arrow.hpp"
25 #include "config.hpp"
26 #include "fake_unit_ptr.hpp"
27 #include "game_board.hpp"
28 #include "play_controller.hpp"
29 #include "resources.hpp"
30 #include "units/unit.hpp"
31 #include "units/map.hpp"
32 
33 namespace wb
34 {
35 
36 std::ostream &operator<<(std::ostream &s, attack_ptr attack)
37 {
38  assert(attack);
39  return attack->print(s);
40 }
41 
42 std::ostream &operator<<(std::ostream &s, attack_const_ptr attack)
43 {
44  assert(attack);
45  return attack->print(s);
46 }
47 
48 std::ostream& attack::print(std::ostream& s) const
49 {
50  s << "Attack on (" << get_target_hex() << ") preceded by ";
51  move::print(s);
52  return s;
53 }
54 
55 attack::attack(std::size_t team_index, bool hidden, unit& u, const map_location& target_hex, int weapon_choice, const pathfind::marked_route& route,
56  arrow_ptr arrow, fake_unit_ptr fake_unit)
57  : move(team_index, hidden, u, route, arrow, std::move(fake_unit)),
58  target_hex_(target_hex),
59  weapon_choice_(weapon_choice),
60  attack_movement_cost_(u.attacks()[weapon_choice_].movement_used()),
62 {
63  this->init();
64 }
65 
66 attack::attack(const config& cfg, bool hidden)
67  : move(cfg,hidden)
68  , target_hex_(cfg.child("target_hex_")["x"],cfg.child("target_hex_")["y"], wml_loc())
69  , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1
72 {
73  // Validate target_hex
75  throw action::ctor_err("attack: Invalid target_hex_");
76 
77  // Validate weapon_choice_
78  if(weapon_choice_ < 0 || weapon_choice_ >= static_cast<int>(get_unit()->attacks().size()))
79  throw action::ctor_err("attack: Invalid weapon_choice_");
80 
81  // Construct attack_movement_cost_
82  assert(get_unit());
83  attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used();
84 
85  this->init();
86 }
87 
89 {
91 }
92 
94 {
95  invalidate();
96 }
97 
99 {
100  v.visit(shared_from_this());
101 }
102 
103 /* private */
105 {
107  {
108  //invalidate dest and target hex so attack indicator is properly cleared
111  }
112 }
113 
114 void attack::execute(bool& success, bool& complete)
115 {
116  if(!valid()) {
117  success = false;
118  //Setting complete to true signifies to side_actions to delete the planned action: nothing more to do with it.
119  complete = true;
120  return;
121  }
122 
123  LOG_WB << "Executing: " << shared_from_this() << "\n";
124 
125  if (route_->steps.size() >= 2)
126  {
127  bool m_success, m_complete;
128  move::execute(m_success,m_complete);
129  if(!m_success) {
130  //Move failed for some reason, so don't attack.
131  success = false;
132  complete = true;
133  return;
134  }
135  }
136 
138  complete = true;
139 
140  //check that attacking unit is still alive, if not, consider the attack a failure
142  if(!survivor.valid() || (!unit_id_.empty() && (survivor->id() != unit_id_)))
143  {
144  success = false;
145  }
146 
147  success = true;
148 }
149 
151 {
152  move::apply_temp_modifier(unit_map);
153  assert(get_unit());
154  unit& unit = *get_unit();
155  DBG_WB << unit.name() << " [" << unit.id()
156  << "] has " << unit.attacks_left() << " attacks, decreasing by one" << "\n";
157  assert(unit.attacks_left() > 0);
158  unit.set_attacks(unit.attacks_left() - 1);
159 
160  //Calculate movement to subtract
162  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
163  << "] from " << unit.movement_left() << " to "
164  << unit.movement_left() - temp_movement_subtracted_ << ".\n";
166 
167  //Update status of fake unit (not undone by remove_temp_modifiers)
168  //@todo this contradicts the name "temp_modifiers"
169  if (fake_unit_) { //Attacks that are not attack-moves don't have fake units
170  fake_unit_->set_movement(unit.movement_left(), true);
171  fake_unit_->set_attacks(unit.attacks_left());
172  }
173 }
174 
176 {
177  assert(get_unit());
178  unit& unit = *get_unit();
179  DBG_WB << unit.name() << " [" << unit.id()
180  << "] has " << unit.attacks_left() << " attacks, increasing by one" << "\n";
181  unit.set_attacks(unit.attacks_left() + 1);
182  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
183  << "] from " << unit.movement_left() << " to "
184  << unit.movement_left() + temp_movement_subtracted_ << ".\n";
187  move::remove_temp_modifier(unit_map);
188 }
189 
191 {
192  if (hex == get_dest_hex() || hex == target_hex_) //draw attack indicator
193  {
194  //@todo: replace this by either the use of transparency + LAYER_ATTACK_INDICATOR,
195  //or a dedicated layer
197 
198  //calculate direction (valid for both hexes)
199  std::string direction_text = map_location::write_direction(
200  get_dest_hex().get_relative_dir(target_hex_));
201 
202  if (hex == get_dest_hex()) //add symbol to attacker hex
203  {
206 
208  image::get_image("whiteboard/attack-indicator-src-" + direction_text + ".png", image::SCALED_TO_HEX));
209  }
210  else if (hex == target_hex_) //add symbol to defender hex
211  {
214 
216  image::get_image("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX));
217  }
218  }
219 }
220 
222 {
223  move::redraw();
225 }
226 
228 {
229  // Verify that the unit that planned this attack exists
230  if(!get_unit()) {
231  return NO_UNIT;
232  }
233  // Verify that the target hex is still valid
234  if(!target_hex_.valid()) {
235  return INVALID_LOCATION;
236  }
237  // Verify that the target hex isn't empty
239  return NO_TARGET;
240  }
241  // Verify that the attacking unit has attacks left
242  if(get_unit()->attacks_left() <= 0) {
243  return NO_ATTACK_LEFT;
244  }
245  // Verify that the attacker and target are enemies
246  if(!resources::gameboard->get_team(get_unit()->side()).is_enemy(resources::gameboard->units().find(target_hex_)->side())){
247  return NOT_AN_ENEMY;
248  }
249  //@todo: (maybe) verify that the target hex contains the same unit that before,
250  // comparing for example the unit ID
251 
252  return move::check_validity();
253 }
254 
256 {
257  config final_cfg = move::to_config();
258 
259  final_cfg["type"] = "attack";
260  final_cfg["weapon_choice_"] = weapon_choice_;
261 // final_cfg["attack_movement_cost_"] = attack_movement_cost_; //Unnecessary
262 // final_cfg["temp_movement_subtracted_"] = temp_movement_subtracted_; //Unnecessary
263 
264  config target_hex_cfg;
265  target_hex_cfg["x"]=target_hex_.wml_x();
266  target_hex_cfg["y"]=target_hex_.wml_y();
267  final_cfg.add_child("target_hex_", std::move(target_hex_cfg));
268 
269  return final_cfg;
270 }
271 
272 } // end namespace wb
map_location target_hex_
the target of the attack
Definition: attack.hpp:79
play_controller * controller
Definition: resources.cpp:21
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: picture.cpp:875
std::string unit_id_
Definition: move.hpp:106
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition: unit.hpp:942
void set_movement(int moves, bool unit_action=false)
Set this unit&#39;s remaining movement to moves.
Definition: unit.cpp:1192
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition: attack.cpp:150
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:114
Arrows destined to be drawn on the map.
unit_iterator end()
Definition: map.hpp:415
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:88
virtual const unit_map & units() const override
Definition: game_board.hpp:114
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:2975
int weapon_choice_
Definition: attack.hpp:81
This class represents a single unit of a specific type.
Definition: unit.hpp:99
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:55
int attack_movement_cost_
Definition: attack.hpp:82
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: attack.cpp:221
std::shared_ptr< attack > attack_ptr
Definition: typedefs.hpp:69
virtual std::ostream & print(std::ostream &s) const
Definition: move.cpp:58
int wml_x() const
Definition: location.hpp:157
virtual void visit(move_ptr move)=0
STL namespace.
int temp_movement_subtracted_
Definition: attack.hpp:83
std::shared_ptr< attack const > attack_const_ptr
Definition: typedefs.hpp:70
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: move.cpp:373
std::shared_ptr< attack > shared_from_this()
Definition: attack.hpp:64
drawing_layer
The layers to render something on.
Definition: display.hpp:815
Definitions for the interface to Wesnoth Markup Language (WML).
virtual error check_validity() const
Check the validity of the action.
Definition: attack.cpp:227
std::size_t team_index() const
Returns the index of the team that owns this action.
Definition: action.hpp:83
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:206
virtual ~attack()
Definition: attack.cpp:93
bool valid()
Returns whether this action is valid or not.
Definition: action.hpp:134
virtual void accept(visitor &v)
Definition: attack.cpp:98
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
const std::string & id() const
Gets this unit&#39;s id.
Definition: unit.hpp:343
Arrows destined to be drawn on the map.
Definition: arrow.hpp:29
virtual map_location get_dest_hex() const
Definition: move.cpp:304
error
Possible errors.
Definition: action.hpp:105
fake_unit_ptr fake_unit_
Definition: move.hpp:113
int wml_y() const
Definition: location.hpp:158
bool valid() const
Definition: location.hpp:93
game_board * gameboard
Definition: resources.cpp:20
virtual error check_validity() const
Check the validity of the action.
Definition: move.cpp:440
const t_string & name() const
Gets this unit&#39;s translatable display name.
Definition: unit.hpp:366
virtual unit_ptr get_unit() const
Return the unit targeted by this action.
Definition: move.cpp:289
Structure which holds a single route and marks for special events.
Definition: pathfind.hpp:140
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition: move.cpp:335
void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: move.cpp:567
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: attack.cpp:255
Encapsulates the map of the game.
Definition: location.hpp:42
unit_iterator find(std::size_t id)
Definition: map.cpp:311
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: attack.cpp:175
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:557
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: move.cpp:506
void set_attacks(int left)
Sets the number of attacks this unit has left this turn.
Definition: unit.hpp:963
void attack_enemy(const map_location &attacker_loc, const map_location &defender_loc, int choice)
static map_location::DIRECTION s
int get_location_y(const map_location &loc) const
Definition: display.cpp:726
const map_location & get_target_hex() const
Definition: attack.hpp:58
#define LOG_WB
Definition: typedefs.hpp:26
config & add_child(config_key_type key)
Definition: config.cpp:476
std::shared_ptr< arrow > arrow_ptr
Definition: typedefs.hpp:59
void drawing_buffer_add(const drawing_layer layer, const map_location &loc, int x, int y, const surface &surf, const SDL_Rect &clip=SDL_Rect())
Add an item to the drawing buffer.
Definition: display.cpp:1177
int get_location_x(const map_location &loc) const
Functions to get the on-screen positions of hexes.
Definition: display.cpp:721
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:63
bool find(E event, F functor)
Tests whether an event handler is available.
#define DBG_WB
Definition: typedefs.hpp:27
Container associating units to locations.
Definition: map.hpp:99
std::ostream & operator<<(std::ostream &s, action_ptr action)
Definition: action.cpp:33
virtual std::ostream & print(std::ostream &s) const
Definition: attack.cpp:48
visitor is an abstract interface : action.accept(visitor) calls visitor.visit(action) ...
std::unique_ptr< pathfind::marked_route > route_
Definition: move.hpp:107
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
bool valid() const
Definition: map.hpp:276
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:190
void invalidate()
invalidates the move-destination and attack-target hexes
Definition: attack.cpp:104
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:139
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:1183
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex...
Definition: move.hpp:32
Definition: display.hpp:48
Footsteps showing path from unit to mouse.
Definition: display.hpp:822
void init()
Definition: attack.cpp:88
Abstract base class for all the visitors (cf GoF Visitor Design Pattern) the whiteboard uses...
Definition: visitor.hpp:31