The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
attack.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2010 - 2025
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 <utility>
23
25
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
35namespace wb
36{
37
38std::ostream &operator<<(std::ostream &s, const attack_ptr& attack)
39{
40 assert(attack);
41 return attack->print(s);
42}
43
44std::ostream &operator<<(std::ostream &s, const attack_const_ptr& attack)
45{
46 assert(attack);
47 return attack->print(s);
48}
49
50std::ostream& attack::print(std::ostream& s) const
51{
52 s << "Attack on (" << get_target_hex() << ") preceded by ";
54 return s;
55}
56
57attack::attack(std::size_t team_index, bool hidden, const 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, std::move(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()),
63 temp_movement_subtracted_(0),
64 attack_count_(u.attacks()[weapon_choice_].attacks_used()),
65 temp_attacks_subtracted_(0)
66{
67 this->init();
68}
69
70attack::attack(const config& cfg, bool hidden)
71 : move(cfg,hidden)
72 , target_hex_(cfg.mandatory_child("target_hex_")["x"], cfg.mandatory_child("target_hex_")["y"], wml_loc())
73 , weapon_choice_(cfg["weapon_choice_"].to_int(-1)) //default value: -1
74 , attack_movement_cost_()
75 , temp_movement_subtracted_(0)
76 , attack_count_()
77 , temp_attacks_subtracted_(0)
78{
79 // Validate target_hex
81 throw action::ctor_err("attack: Invalid target_hex_");
82
83 // Validate weapon_choice_
84 if(weapon_choice_ < 0 || weapon_choice_ >= static_cast<int>(get_unit()->attacks().size()))
85 throw action::ctor_err("attack: Invalid weapon_choice_");
86
87 // Construct attack_movement_cost_
88 assert(get_unit());
89 attack_movement_cost_ = get_unit()->attacks()[weapon_choice_].movement_used();
90 attack_count_ = get_unit()->attacks()[weapon_choice_].attacks_used();
91
92 this->init();
93}
94
99
101{
102 invalidate();
103}
104
106{
108}
109
110/* private */
112{
114 {
115 //invalidate dest and target hex so attack indicator is properly cleared
118 }
119}
120
121void attack::execute(bool& success, bool& complete)
122{
123 if(!valid()) {
124 success = false;
125 //Setting complete to true signifies to side_actions to delete the planned action: nothing more to do with it.
126 complete = true;
127 return;
128 }
129
130 LOG_WB << "Executing: " << shared_from_this();
131
132 if (route_->steps.size() >= 2)
133 {
134 bool m_success, m_complete;
135 move::execute(m_success,m_complete);
136 if(!m_success) {
137 //Move failed for some reason, so don't attack.
138 success = false;
139 complete = true;
140 return;
141 }
142 }
143
145 complete = true;
146
147 //check that attacking unit is still alive, if not, consider the attack a failure
149 if(!survivor.valid() || (!unit_id_.empty() && (survivor->id() != unit_id_)))
150 {
151 success = false;
152 }
153
154 success = true;
155}
156
158{
160 assert(get_unit());
161 unit& unit = *get_unit();
162 DBG_WB << unit.name() << " [" << unit.id()
163 << "] has " << unit.attacks_left() << " attacks, decreasing by " << attack_count_;
164 assert(unit.attacks_left() > 0);
165
166 //Calculate movement to subtract
169 DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
170 << "] from " << unit.movement_left() << " to "
174
175 //Update status of fake unit (not undone by remove_temp_modifiers)
176 //@todo this contradicts the name "temp_modifiers"
177 if (fake_unit_) { //Attacks that are not attack-moves don't have fake units
178 fake_unit_->set_movement(unit.movement_left(), true);
179 fake_unit_->set_attacks(unit.attacks_left());
180 }
181}
182
184{
185 assert(get_unit());
186 unit& unit = *get_unit();
187 DBG_WB << unit.name() << " [" << unit.id()
188 << "] has " << unit.attacks_left() << " attacks, increasing by one";
190 DBG_WB << "Attack: Changing movement points for unit " << unit.name() << " [" << unit.id()
191 << "] from " << unit.movement_left() << " to "
197}
198
199// Draws the attack indicator.
201{
202 if(hex != get_dest_hex() && hex != target_hex_) {
203 return;
204 }
205
206 //@todo: replace this by either the use of transparency + drawing_layer::attack_indicator,
207 //or a dedicated layer
209
210 //calculate direction (valid for both hexes)
211 const std::string direction_text = map_location::write_direction(get_dest_hex().get_relative_dir(target_hex_));
212
213 texture indicator = (hex == get_dest_hex())
214 ? image::get_texture("whiteboard/attack-indicator-src-" + direction_text + ".png", image::HEXED)
215 : image::get_texture("whiteboard/attack-indicator-dst-" + direction_text + ".png", image::HEXED);
216
217 // hex is either the dst or target here. Whichever it is, we want to draw there.
219 layer, hex, [tex = std::move(indicator)](const rect& d) { draw::blit(tex, d); });
220}
221
227
229{
230 // Verify that the unit that planned this attack exists
231 if(!get_unit()) {
232 return NO_UNIT;
233 }
234 // Verify that the target hex is still valid
235 if(!target_hex_.valid()) {
236 return INVALID_LOCATION;
237 }
238 // Verify that the target hex isn't empty
239 if(resources::gameboard->units().find(target_hex_) == resources::gameboard->units().end()){
240 return NO_TARGET;
241 }
242 // Verify that the attacking unit has attacks left
243 if(get_unit()->attacks_left() <= 0) {
244 return NO_ATTACK_LEFT;
245 }
246 // Verify that the attacker and target are enemies
247 if(!resources::gameboard->get_team(get_unit()->side()).is_enemy(resources::gameboard->units().find(target_hex_)->side())){
248 return NOT_AN_ENEMY;
249 }
250 //@todo: (maybe) verify that the target hex contains the same unit that before,
251 // comparing for example the unit ID
252
253 return move::check_validity();
254}
255
257{
258 config final_cfg = move::to_config();
259
260 final_cfg["type"] = "attack";
261 final_cfg["weapon_choice_"] = weapon_choice_;
262// final_cfg["attack_movement_cost_"] = attack_movement_cost_; //Unnecessary
263// final_cfg["temp_movement_subtracted_"] = temp_movement_subtracted_; //Unnecessary
264
265 config target_hex_cfg;
266 target_hex_cfg["x"]=target_hex_.wml_x();
267 target_hex_cfg["y"]=target_hex_.wml_y();
268 final_cfg.add_child("target_hex_", std::move(target_hex_cfg));
269
270 return final_cfg;
271}
272
273} // end namespace wb
static bool is_enemy(std::size_t side, std::size_t other_side)
Arrows destined to be drawn on the map.
Definition arrow.hpp:30
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
config & add_child(std::string_view key)
Definition config.cpp:436
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition display.cpp:2927
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:1241
static display * get_singleton()
Returns the display object if a display object exists.
Definition display.hpp:102
void attack_enemy(const map_location &attacker_loc, const map_location &defender_loc, int choice)
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
virtual const unit_map & units() const override
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
Wrapper class to encapsulate creation and management of an SDL_Texture.
Definition texture.hpp:33
Container associating units to locations.
Definition map.hpp:98
unit_iterator find(std::size_t id)
Definition map.cpp:302
This class represents a single unit of a specific type.
Definition unit.hpp:39
bool valid()
Returns whether this action is valid or not.
Definition action.hpp:135
error
Possible errors.
Definition action.hpp:107
@ INVALID_LOCATION
Definition action.hpp:109
@ NO_ATTACK_LEFT
Definition action.hpp:115
int temp_movement_subtracted_
Definition attack.hpp:84
virtual ~attack()
Definition attack.cpp:100
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition attack.cpp:183
int attack_count_
Definition attack.hpp:85
int temp_attacks_subtracted_
Definition attack.hpp:86
std::shared_ptr< attack > shared_from_this()
Definition attack.hpp:65
void invalidate()
invalidates the move-destination and attack-target hexes
Definition attack.cpp:111
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition attack.cpp:222
virtual error check_validity() const
Check the validity of the action.
Definition attack.cpp:228
virtual void accept(visitor &v)
Definition attack.cpp:105
attack(std::size_t team_index, bool hidden, const 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 apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition attack.cpp:157
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:121
map_location target_hex_
the target of the attack
Definition attack.hpp:80
const map_location & get_target_hex() const
Definition attack.hpp:59
int weapon_choice_
Definition attack.hpp:82
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition attack.cpp:256
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:200
virtual std::ostream & print(std::ostream &s) const
Definition attack.cpp:50
void init()
Definition attack.cpp:95
A planned move, represented on the map by an arrow and a ghosted unit in the destination hex.
Definition move.hpp:36
void redraw()
Redrawing function, called each time the action situation might have changed.
Definition move.cpp:567
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition move.cpp:373
virtual unit_ptr get_unit() const
Return the unit targeted by this action.
Definition move.cpp:289
virtual error check_validity() const
Check the validity of the action.
Definition move.cpp:440
std::string unit_id_
Definition move.hpp:111
std::unique_ptr< pathfind::marked_route > route_
Definition move.hpp:112
virtual std::ostream & print(std::ostream &s) const
Definition move.cpp:58
virtual map_location get_dest_hex() const
Definition move.cpp:304
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition move.cpp:506
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
fake_unit_ptr fake_unit_
Definition move.hpp:118
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
Abstract base class for all the visitors (cf GoF Visitor Design Pattern) the whiteboard uses.
Definition visitor.hpp:33
virtual void visit(move_ptr move)=0
Definitions for the interface to Wesnoth Markup Language (WML).
Drawing functions, for drawing things on the screen.
drawing_layer
@ footsteps
Footsteps showing path from unit to mouse.
const config * cfg
const std::string & id() const
Gets this unit's id.
Definition unit.hpp:286
const t_string & name() const
Gets this unit's translatable display name.
Definition unit.hpp:309
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
Definition unit.hpp:900
void set_attacks(int left)
Sets the number of attacks this unit has left this turn.
Definition unit.hpp:921
void set_movement(int moves, bool unit_action=false)
Set this unit's remaining movement to moves.
Definition unit.cpp:1315
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
Definition unit.hpp:1252
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition location.cpp:541
void blit(const texture &tex, const ::rect &dst)
Draws a texture, or part of a texture, at the given location.
Definition draw.cpp:409
@ HEXED
Standard hexagonal tile mask applied, removing portions that don't fit.
Definition picture.hpp:175
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:955
game_board * gameboard
Definition resources.cpp:20
play_controller * controller
Definition resources.cpp:21
STL namespace.
Definition display.hpp:45
std::shared_ptr< attack > attack_ptr
Definition typedefs.hpp:70
std::shared_ptr< arrow > arrow_ptr
Definition typedefs.hpp:60
std::shared_ptr< attack const > attack_const_ptr
Definition typedefs.hpp:71
std::ostream & operator<<(std::ostream &s, const action_ptr &action)
Definition action.cpp:34
Encapsulates the map of the game.
Definition location.hpp:46
static std::string write_direction(direction dir)
Definition location.cpp:154
bool valid() const
Definition location.hpp:111
int wml_y() const
Definition location.hpp:187
int wml_x() const
Definition location.hpp:186
Structure which holds a single route and marks for special events.
Definition pathfind.hpp:142
An abstract description of a rectangle with integer coordinates.
Definition rect.hpp:49
bool valid() const
Definition map.hpp:273
static map_location::direction s
#define DBG_WB
Definition typedefs.hpp:28
#define LOG_WB
Definition typedefs.hpp:27
visitor is an abstract interface : action.accept(visitor) calls visitor.visit(action)
#define d