The Battle for Wesnoth  1.19.0-dev
undo_move_action.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 - 2024
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 
16 
17 #include "resources.hpp"
18 #include "units/map.hpp"
20 #include "log.hpp"
21 #include "game_display.hpp"
22 #include "units/udisplay.hpp"
23 #include "units/unit.hpp"
24 #include "game_board.hpp"
25 
26 static lg::log_domain log_engine("engine");
27 #define ERR_NG LOG_STREAM(err, log_engine)
28 #define LOG_NG LOG_STREAM(info, log_engine)
29 
30 namespace actions
31 {
32 namespace undo
33 {
34 
36  const std::vector<map_location>::const_iterator & begin,
37  const std::vector<map_location>::const_iterator & end,
38  int sm, int timebonus, int orig, const map_location::DIRECTION dir)
39  : undo_action()
40  , shroud_clearing_action(moved, begin, end, orig, timebonus != 0)
41  , starting_moves(sm)
42  , starting_dir(dir == map_location::NDIRECTIONS ? moved->facing() : dir)
43  , goto_hex(moved->get_goto())
44 {
45 }
46 
47 /**
48  * Writes this into the provided config.
49  */
50 void move_action::write(config & cfg) const
51 {
52  undo_action::write(cfg);
54  cfg["starting_direction"] = map_location::write_direction(starting_dir);
55  cfg["starting_moves"] = starting_moves;
56  config & child = cfg.mandatory_child("unit");
57  child["goto_x"] = goto_hex.wml_x();
58  child["goto_y"] = goto_hex.wml_y();
59 }
60 
61 /**
62  * Reset halo of adjacent units when undo move.
63  */
64 static void reset_adjacent(bool& halo_adjacent, unit_map& units, const map_location& loc)
65 {
66  if(halo_adjacent){
67  unit_map::iterator u = units.find(loc);
68  const auto adjacent = get_adjacent_tiles(loc);
69  for(unsigned i = 0; i < adjacent.size(); ++i) {
70  const unit_map::const_iterator it = units.find(adjacent[i]);
71  if (it == units.end() || it->incapacitated())
72  continue;
73  if ( &*it == &*u )
74  continue;
75  it->anim_comp().set_standing();
76  }
77  }
78 }
79 
80 /**
81  * Undoes this action.
82  * @return true on success; false on an error.
83  */
85 {
87  unit_map & units = resources::gameboard->units();
88 
89  // Copy some of our stored data.
90  const int saved_moves = starting_moves;
91  std::vector<map_location> rev_route = route;
92  std::reverse(rev_route.begin(), rev_route.end());
93 
94  // Check units.
95  unit_map::iterator u = units.find(rev_route.front());
96  const unit_map::iterator u_end = units.find(rev_route.back());
97  if ( u == units.end() || u_end != units.end() ) {
98  //this can actually happen if the scenario designer has abused the [allow_undo] command
99  ERR_NG << "Illegal 'undo' found. Possible abuse of [allow_undo]?";
100  return false;
101  }
102  this->return_village();
103 
104  // Record the unit's current state so it can be redone.
105  starting_moves = u->movement_left();
106  goto_hex = u->get_goto();
107 
108  // Move the unit.
109  unit_display::move_unit(rev_route, u.get_shared_ptr(), true, starting_dir);
110  bool halo_adjacent = false;
111  for (const config::any_child sp : u->abilities().all_children_range()){
112  if(!(sp.cfg)["halo_image"].empty() && (sp.cfg).has_child("affect_adjacent")){
113  halo_adjacent = true;
114  break;
115  }
116  }
117  reset_adjacent(halo_adjacent, units, rev_route.front());
118  units.move(u->get_location(), rev_route.back());
120  reset_adjacent(halo_adjacent, units, rev_route.back());
121 
122  // Restore the unit's old state.
123  u = units.find(rev_route.back());
124  u->set_goto(map_location());
125  u->set_movement(saved_moves, true);
126  u->anim_comp().set_standing();
127 
128  gui.invalidate_unit_after_move(rev_route.front(), rev_route.back());
130  return true;
131 }
132 
133 
134 }
135 }
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:159
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
Definition: config.cpp:367
virtual const unit_map & units() const override
Definition: game_board.hpp:106
static game_display * get_singleton()
Container associating units to locations.
Definition: map.hpp:98
unit_iterator end()
Definition: map.hpp:428
unit_iterator find(std::size_t id)
Definition: map.cpp:302
umap_retval_pair_t move(const map_location &src, const map_location &dst)
Moves a unit from location src to location dst.
Definition: map.cpp:92
static void clear_status_caches()
Clear this unit status cache for all units.
Definition: unit.cpp:695
std::size_t i
Definition: function.cpp:968
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:474
Standard logging facilities (interface).
static void reset_adjacent(bool &halo_adjacent, unit_map &units, const map_location &loc)
Reset halo of adjacent units when undo move.
General purpose widgets.
game_board * gameboard
Definition: resources.cpp:20
void move_unit(const std::vector< map_location > &path, unit_ptr u, bool animate, map_location::DIRECTION dir, bool force_scroll)
Display a unit moving along a given path.
Definition: udisplay.cpp:506
@ moved
All moves and possible attacks have been done.
std::shared_ptr< const unit > unit_const_ptr
Definition: ptr.hpp:27
base class for classes that clear srhoud (move/recruit/recall)
route_t route
The hexes occupied by the affected unit during this action.
void return_village()
Change village owner on undo.
virtual bool undo(int side)
Undoes this action.
map_location::DIRECTION starting_dir
move_action(const unit_const_ptr moved, const std::vector< map_location >::const_iterator &begin, const std::vector< map_location >::const_iterator &end, int sm, int timebonus, int orig, const map_location::DIRECTION dir)
virtual void write(config &cfg) const
Writes this into the provided config.
actions that are undoable (this does not include update_shroud and auto_shroud)
Definition: undo_action.hpp:66
virtual void write(config &cfg) const
Writes this into the provided config.
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
int wml_y() const
Definition: location.hpp:154
int wml_x() const
Definition: location.hpp:153
static std::string write_direction(DIRECTION dir)
Definition: location.cpp:140
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
Definition: map.hpp:217
Display units performing various actions: moving, attacking, and dying.
static lg::log_domain log_engine("engine")
#define ERR_NG