The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
attack.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 - 2016 by Gabriel Morin <gabrielmorin (at) gmail (dot) com>
3  Part of the Battle for Wesnoth Project http://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 "attack.hpp"
20 
21 #include "visitor.hpp"
22 #include "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(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, fake_unit),
58  target_hex_(target_hex),
59  weapon_choice_(weapon_choice),
60  attack_movement_cost_(get_unit()->attacks()[weapon_choice_].movement_used()),
61  temp_movement_subtracted_(0)
62 {
63  this->init();
64 }
65 
66 attack::attack(config const& cfg, bool hidden)
67  : move(cfg,hidden)
68  , target_hex_(cfg.child("target_hex_")["x"],cfg.child("target_hex_")["y"])
69  , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1
70  , attack_movement_cost_()
71  , temp_movement_subtracted_(0)
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  attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used();
83 
84  this->init();
85 }
86 
88 {
90 }
91 
93 {
94  invalidate();
95 }
96 
98 {
100 }
101 
102 /* private */
104 {
106  {
107  //invalidate dest and target hex so attack indicator is properly cleared
110  }
111 }
112 
113 void attack::execute(bool& success, bool& complete)
114 {
115  if(!valid()) {
116  success = false;
117  //Setting complete to true signifies to side_actions to delete the planned action: nothing more to do with it.
118  complete = true;
119  return;
120  }
121 
122  LOG_WB << "Executing: " << shared_from_this() << "\n";
123 
124  if (route_->steps.size() >= 2)
125  {
126  bool m_success, m_complete;
127  move::execute(m_success,m_complete);
128  if(!m_success) {
129  //Move failed for some reason, so don't attack.
130  success = false;
131  complete = true;
132  return;
133  }
134  }
135 
137  complete = true;
138 
139  //check that attacking unit is still alive, if not, consider the attack a failure
141  if(!survivor.valid() || survivor->id() != unit_id_)
142  {
143  success = false;
144  }
145 
146  success = true;
147 }
148 
150 {
151  move::apply_temp_modifier(unit_map);
152  assert(get_unit());
153  unit& unit = *get_unit();
154  DBG_WB << unit.name() << " [" << unit.id()
155  << "] has " << unit.attacks_left() << " attacks, decreasing by one" << "\n";
156  assert(unit.attacks_left() > 0);
157  unit.set_attacks(unit.attacks_left() - 1);
158 
159  //Calculate movement to subtract
161  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
162  << "] from " << unit.movement_left() << " to "
163  << unit.movement_left() - temp_movement_subtracted_ << ".\n";
165 
166  //Update status of fake unit (not undone by remove_temp_modifiers)
167  //@todo this contradicts the name "temp_modifiers"
168  if (fake_unit_) { //Attacks that are not attack-moves don't have fake units
169  fake_unit_->set_movement(unit.movement_left(), true);
170  fake_unit_->set_attacks(unit.attacks_left());
171  }
172 }
173 
175 {
176  assert(get_unit());
177  unit& unit = *get_unit();
178  DBG_WB << unit.name() << " [" << unit.id()
179  << "] has " << unit.attacks_left() << " attacks, increasing by one" << "\n";
180  unit.set_attacks(unit.attacks_left() + 1);
181  DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
182  << "] from " << unit.movement_left() << " to "
183  << unit.movement_left() + temp_movement_subtracted_ << ".\n";
186  move::remove_temp_modifier(unit_map);
187 }
188 
190 {
191  if (hex == get_dest_hex() || hex == target_hex_) //draw attack indicator
192  {
193  //@todo: replace this by either the use of transparency + LAYER_ATTACK_INDICATOR,
194  //or a dedicated layer
196 
197  //calculate direction (valid for both hexes)
199  get_dest_hex().get_relative_dir(target_hex_));
200 
201 #ifdef SDL_GPU
202  if (hex == get_dest_hex()) //add symbol to attacker hex
203  {
206 
207  resources::screen->drawing_buffer_add(layer, get_dest_hex(), xpos, ypos,
208  image::get_texture("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_texture("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX));
217  }
218 #else
219  if (hex == get_dest_hex()) //add symbol to attacker hex
220  {
223 
224  resources::screen->drawing_buffer_add(layer, get_dest_hex(), xpos, ypos,
225  image::get_image("whiteboard/attack-indicator-src-" + direction_text + ".png", image::SCALED_TO_HEX));
226  }
227  else if (hex == target_hex_) //add symbol to defender hex
228  {
231 
233  image::get_image("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::SCALED_TO_HEX));
234  }
235 #endif
236  }
237 }
238 
240 {
241  move::redraw();
243 }
244 
246 {
247  // Verify that the unit that planned this attack exists
248  if(!get_unit()) {
249  return NO_UNIT;
250  }
251  // Verify that the target hex is still valid
252  if(!target_hex_.valid()) {
253  return INVALID_LOCATION;
254  }
255  // Verify that the target hex isn't empty
257  return NO_TARGET;
258  }
259  // Verify that the attacking unit has attacks left
260  if(get_unit()->attacks_left() <= 0) {
261  return NO_ATTACK_LEFT;
262  }
263  // Verify that the attacker and target are enemies
264  if(!(*resources::teams)[get_unit()->side() - 1].is_enemy(resources::units->find(target_hex_)->side())){
265  return NOT_AN_ENEMY;
266  }
267  //@todo: (maybe) verify that the target hex contains the same unit that before,
268  // comparing for example the unit ID
269 
270  return move::check_validity();
271 }
272 
274 {
275  config final_cfg = move::to_config();
276 
277  final_cfg["type"] = "attack";
278  final_cfg["weapon_choice_"] = weapon_choice_;
279 // final_cfg["attack_movement_cost_"] = attack_movement_cost_; //Unnecessary
280 // final_cfg["temp_movement_subtracted_"] = temp_movement_subtracted_; //Unnecessary
281 
282  config target_hex_cfg;
283  target_hex_cfg["x"]=target_hex_.x;
284  target_hex_cfg["y"]=target_hex_.y;
285  final_cfg.add_child("target_hex_",target_hex_cfg);
286 
287  return final_cfg;
288 }
289 
290 } // end namespace wb
map_location target_hex_
the target of the attack
Definition: attack.hpp:80
play_controller * controller
Definition: resources.cpp:21
void drawing_buffer_add(const tdrawing_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:1241
boost::shared_ptr< attack > shared_from_this()
Definition: attack.hpp:65
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:878
std::string unit_id_
Definition: move.hpp:103
events::mouse_handler & get_mouse_handler_base()
Get a reference to a mouse handler member a derived class uses.
const std::string & id() const
Definition: unit.hpp:148
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition: attack.cpp:149
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:113
Arrows destined to be drawn on the map.
unit_iterator end()
Definition: map.hpp:311
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: move.cpp:493
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3536
int weapon_choice_
Definition: attack.hpp:82
Definition: unit.hpp:95
const t_string & name() const
The unit name for display.
Definition: unit.hpp:158
int attack_movement_cost_
Definition: attack.hpp:83
virtual map_location get_dest_hex() const
Definition: move.cpp:300
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: attack.cpp:239
virtual error check_validity() const
Check the validity of the action.
Definition: move.cpp:429
game_display * screen
Definition: resources.cpp:27
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition: attack.cpp:273
Footsteps showing path from unit to mouse.
Definition: display.hpp:871
virtual void visit(move_ptr move)=0
int get_location_x(const map_location &loc) const
Functions to get the on-screen positions of hexes.
Definition: display.cpp:713
virtual std::ostream & print(std::ostream &s) const
Definition: move.cpp:56
map_location const & get_target_hex() const
Definition: attack.hpp:59
int temp_movement_subtracted_
Definition: attack.hpp:84
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: move.cpp:362
Definitions for the interface to Wesnoth Markup Language (WML).
int get_location_y(const map_location &loc) const
Definition: display.cpp:718
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:205
virtual ~attack()
Definition: attack.cpp:92
tdrawing_layer
The layers to render something on.
Definition: display.hpp:864
bool valid()
Returns whether this action is valid or not.
Definition: action.hpp:133
virtual void accept(visitor &v)
Definition: attack.cpp:97
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.hpp:314
std::vector< team > * teams
Definition: resources.cpp:29
GLenum GLenum GLuint GLint GLint layer
Definition: glew.h:3455
Arrows destined to be drawn on the map.
Definition: arrow.hpp:30
bool valid() const
Definition: location.hpp:69
virtual error check_validity() const
Check the validity of the action.
Definition: attack.cpp:245
error
Possible errors.
Definition: action.hpp:104
fake_unit_ptr fake_unit_
Definition: move.hpp:110
const GLdouble * v
Definition: glew.h:1359
config & add_child(const std::string &key)
Definition: config.cpp:743
boost::scoped_ptr< pathfind::marked_route > route_
Definition: move.hpp:104
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:327
int movement_left() const
Returns how far a unit can move this turn (zero if incapacitated).
Definition: unit.hpp:220
void redraw()
Redrawing function, called each time the action situation might have changed.
Definition: move.cpp:554
virtual unit_ptr get_unit() const
Return the unit targeted by this action.
Definition: move.cpp:285
Encapsulates the map of the game.
Definition: location.hpp:38
virtual std::ostream & print(std::ostream &s) const
Definition: attack.cpp:48
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition: attack.cpp:174
void attack_enemy(const map_location &attacker_loc, const map_location &defender_loc, int choice)
int attacks_left() const
Definition: unit.hpp:230
attack(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
void set_movement(int moves, bool unit_action=false)
Set the unit's remaining movement to moves.
Definition: unit.cpp:1148
#define LOG_WB
Definition: typedefs.hpp:28
GLsizeiptr size
Definition: glew.h:1649
bool find(E event, F functor)
Tests whether an event handler is available.
#define DBG_WB
Definition: typedefs.hpp:29
Container associating units to locations.
Definition: map.hpp:90
std::ostream & operator<<(std::ostream &s, action_ptr action)
Definition: action.cpp:33
void set_attacks(int left)
Definition: unit.hpp:233
unit_iterator find(size_t id)
Definition: map.cpp:285
bool valid() const
Definition: map.hpp:229
visitor is an abstract interface : action.accept(visitor) calls visitor.visit(action) ...
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
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:189
GLdouble s
Definition: glew.h:1358
void invalidate()
invalidates the move-destination and attack-target hexes
Definition: attack.cpp:103
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:144
GLsizei const GLcharARB ** string
Definition: glew.h:4503
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
unit_map * units
Definition: resources.cpp:35
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex...
Definition: move.hpp:33
Definition: display.hpp:47
void init()
Definition: attack.cpp:87
Abstract base class for all the visitors (cf GoF Visitor Design Pattern) the whiteboard uses...
Definition: visitor.hpp:32