The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
unit_creator.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
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  * Recruiting, recalling.
18  */
19 
20 #include "actions/unit_creator.hpp"
21 
22 #include "actions/move.hpp" //for actions::get_village
23 
24 #include "config.hpp"
25 #include "filter_context.hpp"
26 #include "game_board.hpp"
27 #include "game_events/pump.hpp"
28 #include "preferences/game.hpp"
29 #include "game_data.hpp" // for resources::gamedata conversion variable_set
30 #include "gettext.hpp"
31 #include "log.hpp"
32 #include "map/map.hpp"
33 #include "pathfind/pathfind.hpp"
34 #include "resources.hpp" // for resources::screen, resources::gamedata
35 #include "team.hpp" //for team
36 #include "units/unit.hpp" // for unit
37 #include "units/udisplay.hpp" // for unit_display
38 #include "variable.hpp" // for vconfig
39 
40 #include "game_display.hpp" // for resources::screen
41 
42 static lg::log_domain log_engine("engine");
43 #define DBG_NG LOG_STREAM(debug, log_engine)
44 #define LOG_NG LOG_STREAM(info, log_engine)
45 #define WARN_NG LOG_STREAM(warn, log_engine)
46 #define ERR_NG LOG_STREAM(err, log_engine)
47 
49  : add_to_recall_(false)
50  , discover_(false)
51  , get_village_(false)
52  , invalidate_(false)
53  , rename_side_(false)
54  , show_(false)
55  , start_pos_(start_pos)
56  , team_(tm)
57  , board_(board ? board : resources::gameboard)
58 {
59 }
60 
61 
63 {
64  show_ = b;
65  return *this;
66 }
67 
68 
70 {
71  get_village_ = b;
72  return *this;
73 }
74 
75 
77 {
78  rename_side_ = b;
79  return *this;
80 }
81 
83 {
84  invalidate_ = b;
85  return *this;
86 }
87 
88 
90 {
91  discover_ = b;
92  return *this;
93 }
94 
95 
97 {
98  add_to_recall_ = b;
99  return *this;
100 }
101 
102 
103 map_location unit_creator::find_location(const config &cfg, const unit* pass_check)
104 {
105 
106  DBG_NG << "finding location for unit with id=["<<cfg["id"]<<"] placement=["<<cfg["placement"]<<"] x=["<<cfg["x"]<<"] y=["<<cfg["y"]<<"] for side " << team_.side() << "\n";
107 
108  std::vector<std::string> placements = utils::split(cfg["placement"]);
109 
110  placements.push_back("map");
111  placements.push_back("recall");
112 
113  bool pass = cfg["passable"].to_bool(false);
114  bool vacant = !cfg["overwrite"].to_bool(false);
115 
116  for (const std::string& place : placements)
117  {
118  map_location loc;
119 
120  if ( place == "recall" ) {
122  }
123 
124  else if ( place == "leader" || place == "leader_passable" ) {
126  //todo: take 'leader in recall list' possibility into account
127  if (leader.valid()) {
128  loc = leader->get_location();
129  } else {
130  loc = start_pos_;
131  }
132  if(place == "leader_passable") {
133  WARN_NG << "placement=leader_passable is deprecated; please use placement=leader and passable=yes instead\n";
134  pass = true;
135  }
136  }
137 
138  // "map", "map_passable", and "map_overwrite".
139  else if(place == "map" || place == "map_passable" || place == "map_overwrite") {
140  if(cfg.has_attribute("location_id")) {
141  loc = board_->map().special_location(cfg["location_id"]);
142  }
143  if(!loc.valid()) {
144  loc = map_location(cfg, resources::gamedata);
145  }
146  if(place == "map_passable") {
147  WARN_NG << "placement=map_passable is deprecated; please use placement=map and passable=yes instead\n";
148  pass = true;
149  } else if(place == "map_overwrite") {
150  WARN_NG << "placement=map_overwrite is deprecated; please use placement=map and overwrite=yes instead\n";
151  vacant = false;
152  }
153  }
154 
155  if(loc.valid() && board_->map().on_board(loc)) {
156  if(vacant) {
158  pass ? pass_check : nullptr, nullptr, board_);
159  }
160  if(loc.valid() && board_->map().on_board(loc)) {
161  return loc;
162  }
163  }
164  }
165 
167 
168 }
169 
170 
171 void unit_creator::add_unit(const config &cfg, const vconfig* vcfg)
172 {
173  config temp_cfg(cfg);
174  temp_cfg["side"] = team_.side();
175 
176  const std::string& id =(cfg)["id"];
177  bool animate = temp_cfg["animate"].to_bool();
178  bool fire_event = temp_cfg["fire_event"].to_bool(true);
179  temp_cfg.remove_attribute("animate");
180 
181  unit_ptr recall_list_element = team_.recall_list().find_if_matches_id(id);
182 
183  if ( !recall_list_element ) {
184  //make the new unit
185  unit_ptr new_unit(new unit(temp_cfg, true, vcfg));
186  map_location loc = find_location(temp_cfg, new_unit.get());
187  if ( loc.valid() ) {
188  //add the new unit to map
189  board_->units().replace(loc, new_unit);
190  LOG_NG << "inserting unit for side " << new_unit->side() << "\n";
191  post_create(loc,*(board_->units().find(loc)),animate,fire_event);
192  }
193  else if ( add_to_recall_ ) {
194  //add to recall list
195  team_.recall_list().add(new_unit);
196  DBG_NG << "inserting unit with id=["<<id<<"] on recall list for side " << new_unit->side() << "\n";
197  preferences::encountered_units().insert(new_unit->type_id());
198  }
199  } else {
200  //get unit from recall list
201  map_location loc = find_location(temp_cfg, recall_list_element.get());
202  if ( loc.valid() ) {
203  board_->units().replace(loc, recall_list_element);
204  LOG_NG << "inserting unit from recall list for side " << recall_list_element->side()<< " with id="<< id << "\n";
205  post_create(loc,*(board_->units().find(loc)),animate,fire_event);
206  //if id is not empty, delete units with this ID from recall list
208  }
209  else if ( add_to_recall_ ) {
210  LOG_NG << "wanted to insert unit on recall list, but recall list for side " << (cfg)["side"] << "already contains id=" <<id<<"\n";
211  return;
212  }
213  }
214 }
215 
216 
217 void unit_creator::post_create(const map_location &loc, const unit &new_unit, bool anim, bool fire_event)
218 {
219 
220  if (discover_) {
221  preferences::encountered_units().insert(new_unit.type_id());
222  }
223 
224  bool show = show_ && (resources::screen !=nullptr) && !resources::screen->fogged(loc);
225  bool animate = show && anim;
226 
227  if (get_village_) {
228  assert(resources::gameboard);
229  if (board_->map().is_village(loc)) {
230  actions::get_village(loc, new_unit.side());
231  }
232  }
233 
234  // Only fire the events if it's safe; it's not if we're in the middle of play_controller::reset_gamestate()
235  if (fire_event && resources::lua_kernel != nullptr) {
236  resources::game_events->pump().fire("unit_placed", loc);
237  }
238 
239  if (resources::screen!=nullptr) {
240 
241  if (invalidate_ ) {
243  }
244 
245  if (animate) {
247  } else if (show) {
249  }
250  }
251 }
unit_creator & allow_rename_side(bool b)
Game board class.
Definition: game_board.hpp:50
bool fire_event(const ui_event event, std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&...params)
Helper function for fire_event.
virtual const unit_map & units() const
Definition: game_board.hpp:97
std::vector< char_t > string
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:2981
This class represents a single unit of a specific type.
Definition: unit.hpp:101
void show(CVideo &video, const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
Definition: tooltip.cpp:153
static lg::log_domain log_engine("engine")
unit_creator & allow_invalidate(bool b)
unit_creator & allow_show(bool b)
unit_iterator find_leader(int side)
Definition: map.cpp:329
bool is_village(const map_location &loc) const
Definition: map.cpp:66
game_display * screen
Definition: resources.cpp:27
map_location find_vacant_tile(const map_location &loc, VACANT_TILE_TYPE vacancy, const unit *pass_check, const team *shroud_check, const game_board *board)
Function that will find a location on the board that is as near to loc as possible, but which is unoccupied by any units.
Definition: pathfind.cpp:54
unit_creator & allow_discover(bool b)
virtual void draw()
Draws invalidated items.
Definition: display.cpp:2432
const std::string & type_id() const
The id of this unit's type.
Definition: unit.hpp:268
-file sdl_utils.hpp
void remove_attribute(config_key_type key)
Definition: config.cpp:218
Definitions for the interface to Wesnoth Markup Language (WML).
unit_creator & allow_add_to_recall(bool b)
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
game_data * gamedata
Definition: resources.cpp:22
#define b
umap_retval_pair_t replace(const map_location &l, unit_ptr p)
Works like unit_map::add; but l is emptied first, if needed.
Definition: map.cpp:225
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:44
unit_ptr find_if_matches_id(const std::string &unit_id)
Find a unit by id. Null pointer if not found.
#define LOG_NG
bool valid() const
Definition: location.hpp:72
game_board * gameboard
Definition: resources.cpp:20
const map_location start_pos_
static const map_location & null_location()
Definition: location.hpp:220
game_events::manager * game_events
Definition: resources.cpp:24
void erase_if_matches_id(const std::string &unit_id)
Erase any unit with this id.
Encapsulates the map of the game.
Definition: location.hpp:40
Various functions related to moving units.
bool has_attribute(config_key_type key) const
Definition: config.cpp:196
map_location special_location(const std::string &id) const
Definition: map.cpp:311
unit_creator & allow_get_village(bool b)
Various functions related to the creation of units (recruits, recalls, and placed units)...
Define the game's event mechanism.
void post_create(const map_location &loc, const unit &new_unit, bool anim, bool fire_event)
std::set< std::string > & encountered_units()
Definition: game.cpp:942
int side() const
Definition: team.hpp:187
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
Definition: pump.cpp:493
virtual const gamemap & map() const
Definition: game_board.hpp:96
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:369
void add_unit(const config &cfg, const vconfig *vcfg=nullptr)
adds a unit on map without firing any events (so, usable during team construction in gamestatus) ...
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
Definition: move.cpp:139
boost::intrusive_ptr< unit > unit_ptr
Definition: ptr.hpp:29
map_location find_location(const config &cfg, const unit *pass_check=nullptr)
finds a suitable location for unit
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:624
void unit_recruited(const map_location &loc, const map_location &leader_loc)
Definition: udisplay.cpp:712
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
Standard logging facilities (interface).
recall_list_manager & recall_list()
Definition: team.hpp:214
void add(const unit_ptr &ptr)
Add a unit to the list.
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
game_events::wml_event_pump & pump()
Definition: manager.cpp:217
#define WARN_NG
unit_iterator find(size_t id)
Definition: map.cpp:311
unit_creator(team &tm, const map_location &start_pos, game_board *board=nullptr)
bool valid() const
Definition: map.hpp:276
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
This module contains various pathfinding functions and utilities.
int side() const
The side this unit belongs to.
Definition: unit.hpp:245
game_board * board_
Display units performing various actions: moving, attacking, and dying.
#define DBG_NG