The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
recruit.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
21
25
26#include "fake_unit_ptr.hpp"
27#include "menu_events.hpp"
28#include "play_controller.hpp"
29#include "resources.hpp"
30#include "units/unit.hpp"
32#include "units/map.hpp"
33#include "units/types.hpp"
34#include "utils/general.hpp"
35
36namespace wb
37{
38
39std::ostream& operator<<(std::ostream& s, const recruit_ptr& recruit)
40{
41 assert(recruit);
42 return recruit->print(s);
43}
44std::ostream& operator<<(std::ostream& s, const recruit_const_ptr& recruit)
45{
46 assert(recruit);
47 return recruit->print(s);
48}
49
50std::ostream& recruit::print(std::ostream &s) const
51{
52 s << "Recruiting " << unit_name_ << " on hex " << recruit_hex_;
53 return s;
54}
55
56recruit::recruit(std::size_t team_index, bool hidden, const std::string& unit_name, const map_location& recruit_hex):
57 action(team_index,hidden),
58 unit_name_(unit_name),
59 recruit_hex_(recruit_hex),
60 temp_unit_(create_corresponding_unit()), //auto-ptr ownership transfer
61 fake_unit_(temp_unit_->clone()), //temp_unit_ *copied* into new fake unit
62 cost_(0)
63{
64 this->init();
65}
66
67recruit::recruit(const config& cfg, bool hidden)
68 : action(cfg,hidden)
69 , unit_name_(cfg["unit_name_"])
70 , recruit_hex_(cfg.mandatory_child("recruit_hex_")["x"],cfg.mandatory_child("recruit_hex_")["y"], wml_loc())
71 , temp_unit_()
72 , fake_unit_()
73 , cost_(0)
74{
75 // Validate unit_name_
77 throw action::ctor_err("recruit: Invalid recruit unit type");
78
79 // Construct temp_unit_ and fake_unit_
80 temp_unit_ = create_corresponding_unit(); //auto-ptr ownership transfer
81 fake_unit_.reset(temp_unit_->clone()); //temp_unit_ copied into new fake_unit
82
83 this->init();
84}
85
87{
88 temp_unit_->set_movement(0, true);
89 temp_unit_->set_attacks(0);
90
91 fake_unit_->set_location(recruit_hex_);
92 fake_unit_->set_movement(0, true);
93 fake_unit_->set_attacks(0);
94 fake_unit_->anim_comp().set_ghosted(false);
96
97 cost_ = fake_unit_->type().cost();
98}
99
103
105{
107}
108
109void recruit::execute(bool& success, bool& complete)
110{
111 assert(valid());
112 temporary_unit_hider const raii(*fake_unit_);
113 const std::size_t old_id = fake_unit_->underlying_id();
115 const int side_num = team_index() + 1;
116 //Give back the spent gold so we don't get "not enough gold" message
117 resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(-cost_);
118 bool const result = resources::controller->get_menu_handler().do_recruit(unit_name_, side_num, loc);
119 //If it failed, take back the gold
120 if (!result) {
121 resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(cost_);
122 }
123 else {
124 auto mit = resources::gameboard->units().find(loc);
125 if(mit != resources::gameboard->units().end()) {
126 viewer_actions()->update_recruited_unit(old_id, *mit);
127 }
128
129 }
130 success = complete = result;
131}
132
134{
135 assert(valid());
136 temp_unit_->set_location(recruit_hex_);
137
138 DBG_WB << "Inserting future recruit [" << temp_unit_->id()
139 << "] at position " << temp_unit_->get_location() << ".";
140
141 // Add cost to money spent on recruits.
142 resources::gameboard->teams().at(team_index()).get_side_actions()->change_gold_spent_by(cost_);
143
144 // Temporarily insert unit into unit_map
145 // unit map takes ownership of temp_unit
146 const std::size_t old_id = temp_unit_->underlying_id();
148
149 //in the past there was a bug where the map changed the unit ids here (because a unit with that id already existed) which caused crashes later.
150 assert(temp_unit_->underlying_id() == old_id);
151
152 // Update gold in the top bar
154}
155
157{
158 //Unit map gives back ownership of temp_unit_
160
161 //remove simulated unit refresh on new turn done by mapbuilder.
162 temp_unit_->set_movement(0, true);
163 temp_unit_->set_attacks(0);
164
165 assert(temp_unit_.get());
166}
167
169{
170 if (hex == recruit_hex_)
171 {
172 const double x_offset = 0.5;
173 const double y_offset = 0.7;
174 //position 0,0 in the hex is the upper left corner
175 std::stringstream number_text;
176 number_text << font::unicode_minus << cost_;
177 std::size_t font_size = 16;
178 color_t color {255, 0, 0}; //red
180 number_text.str(), font_size, color, x_offset, y_offset);
181 }
182}
183
188
189
191{
192 unit_type const* type = unit_types.find(unit_name_);
193 assert(type);
194 int side_num = team_index() + 1;
195 //real_unit = false needed to avoid generating random traits and causing OOS
196 bool real_unit = false;
197 unit_ptr result = unit::create(*type, side_num, real_unit);
198 result->set_movement(0, true);
199 result->set_attacks(0);
200 return result; //ownership gets transferred to returned unique_ptr copy
201}
202
204{
205 //Check that destination hex is still free
206 if(resources::gameboard->units().find(recruit_hex_) != resources::gameboard->units().end()) {
207 return LOCATION_OCCUPIED;
208 }
209 //Check that unit to recruit is still in side's recruit list
210 const std::set<std::string>& recruits = resources::gameboard->teams()[team_index()].recruits();
211 if(recruits.find(unit_name_) == recruits.end()) {
212 bool in_extra_recruit = any_recruiter(team_index() + 1, get_recruit_hex(), [&](unit& leader) {
213 return utils::contains(leader.recruits(), unit_name_);
214 });
215 if (!in_extra_recruit) {
216 return UNIT_UNAVAILABLE;
217 }
218 }
219 //Check that there is still enough gold to recruit this unit
220 if(temp_unit_->cost() > resources::gameboard->teams()[team_index()].gold()) {
221 return NOT_ENOUGH_GOLD;
222 }
223 //Check that there is a leader available to recruit this unit
225 return NO_LEADER;
226 }
227
228 return OK;
229}
230
232{
233 config final_cfg = action::to_config();
234
235 final_cfg["type"] = "recruit";
236 final_cfg["unit_name_"] = unit_name_;
237// final_cfg["temp_cost_"] = temp_cost_; //Unnecessary
238
239 config loc_cfg;
240 loc_cfg["x"]=recruit_hex_.wml_x();
241 loc_cfg["y"]=recruit_hex_.wml_y();
242 final_cfg.add_child("recruit_hex_", std::move(loc_cfg));
243
244 return final_cfg;
245}
246
247void recruit::do_hide() {fake_unit_->set_hidden(true);}
248void recruit::do_show() {fake_unit_->set_hidden(false);}
249
250}
map_location loc
Definition move.cpp:172
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
void draw_text_in_hex(const map_location &loc, const drawing_layer layer, const std::string &text, std::size_t font_size, color_t color, double x_in_hex=0.5, double y_in_hex=0.5)
Draw text on a hex.
Definition display.cpp:1358
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition display.cpp:2927
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
Definition display.hpp:308
static display * get_singleton()
Returns the display object if a display object exists.
Definition display.hpp:102
bool do_recruit(const std::string &type, int side_num, const map_location &target_hex)
void reset()
Reset the internal unit pointer, and deregister from the manager.
void place_on_fake_unit_manager(fake_unit_manager *d)
Place this on manager's fake_units_ dequeue.
virtual const std::vector< team > & teams() const override
virtual const unit_map & units() const override
events::menu_handler & get_menu_handler()
Container associating units to locations.
Definition map.hpp:98
unit_ptr extract(const map_location &loc)
Extracts a unit from the map.
Definition map.cpp:259
unit_iterator find(std::size_t id)
Definition map.cpp:302
umap_retval_pair_t insert(const unit_ptr &p)
Inserts the unit pointed to by p into the map.
Definition map.cpp:135
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition types.cpp:1253
A single unit type that the player may recruit.
Definition types.hpp:43
This class represents a single unit of a specific type.
Definition unit.hpp:39
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
Definition unit.hpp:107
Abstract base class for all the whiteboard planned actions.
Definition action.hpp:34
bool valid()
Returns whether this action is valid or not.
Definition action.hpp:135
std::size_t team_index() const
Returns the index of the team that owns this action.
Definition action.hpp:84
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition action.cpp:51
error
Possible errors.
Definition action.hpp:107
@ NOT_ENOUGH_GOLD
Definition action.hpp:118
@ LOCATION_OCCUPIED
Definition action.hpp:112
@ UNIT_UNAVAILABLE
Definition action.hpp:117
virtual error check_validity() const
Check the validity of the action.
Definition recruit.cpp:203
std::string unit_name_
Definition recruit.hpp:85
virtual void do_hide()
Called by the non-virtual hide() and show(), respectively.
Definition recruit.cpp:247
fake_unit_ptr fake_unit_
Definition recruit.hpp:89
virtual std::ostream & print(std::ostream &s) const
Definition recruit.cpp:50
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 recruit.cpp:168
map_location const get_recruit_hex() const
Definition recruit.hpp:75
virtual config to_config() const
Constructs and returns a config object representing this object.
Definition recruit.cpp:231
map_location recruit_hex_
Definition recruit.hpp:86
std::shared_ptr< recruit > shared_from_this()
Definition recruit.hpp:81
unit_ptr temp_unit_
Definition recruit.hpp:88
virtual void do_show()
Definition recruit.cpp:248
virtual void execute(bool &success, bool &complete)
Output parameters: success: Whether or not to continue an execute-all after this execution complete: ...
Definition recruit.cpp:109
recruit(std::size_t team_index, bool hidden, const std::string &unit_name, const map_location &recruit_hex)
Definition recruit.cpp:56
virtual void apply_temp_modifier(unit_map &unit_map)
Applies temporarily the result of this action to the specified unit map.
Definition recruit.cpp:133
void init()
Definition recruit.cpp:86
virtual ~recruit()
Definition recruit.cpp:100
unit_ptr create_corresponding_unit()
Definition recruit.cpp:190
virtual void remove_temp_modifier(unit_map &unit_map)
Removes the result of this action from the specified unit map.
Definition recruit.cpp:156
virtual void accept(visitor &v)
Definition recruit.cpp:104
virtual void redraw()
Redrawing function, called each time the action situation might have changed.
Definition recruit.cpp:184
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
@ actions_numbering
Move numbering for the whiteboard.
const config * cfg
const std::set< std::string > & recruits() const
The type IDs of the other units this unit may recruit, if possible.
Definition unit.hpp:546
const std::string unicode_minus
Definition constants.cpp:42
game_board * gameboard
Definition resources.cpp:20
fake_unit_manager * fake_units
Definition resources.cpp:30
play_controller * controller
Definition resources.cpp:21
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition general.hpp:88
Definition display.hpp:45
std::shared_ptr< recruit > recruit_ptr
Definition typedefs.hpp:72
unit * find_recruiter(std::size_t team_index, const map_location &hex)
Definition utility.cpp:70
std::shared_ptr< recruit const > recruit_const_ptr
Definition typedefs.hpp:73
side_actions_ptr viewer_actions()
Definition utility.cpp:42
bool any_recruiter(int team_num, const map_location &loc, const std::function< bool(unit &)> &func)
executes func for each unti of side of side_num that can recruit on loc.
Definition utility.cpp:83
std::ostream & operator<<(std::ostream &s, const action_ptr &action)
Definition action.cpp:34
std::shared_ptr< unit > unit_ptr
Definition ptr.hpp:26
static config unit_name(const unit *u)
Definition reports.cpp:163
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
Encapsulates the map of the game.
Definition location.hpp:46
int wml_y() const
Definition location.hpp:187
int wml_x() const
Definition location.hpp:186
static map_location::direction s
#define DBG_WB
Definition typedefs.hpp:28
unit_type_data unit_types
Definition types.cpp:1499
visitor is an abstract interface : action.accept(visitor) calls visitor.visit(action)