make sure units are always stored in unit_ptr step2

previously the unit ctor could invoke arbitrary umc lua code, for
example via advance_to -> add_modification ->
resources::lua_kernel->apply_effect and during that call the unit was
not owned by a unit_ptr, so the code could not use unit_ptr objects at
several places because the unit might not be owned by a unit_ptr object.
This commit is contained in:
gfgtdf 2018-03-10 14:46:04 +01:00 committed by Celtic Minstrel
parent b2cb4be47d
commit a32f6aaf64
27 changed files with 152 additions and 164 deletions

View file

@ -284,7 +284,7 @@ unit_ptr get_advanced_unit(const unit &u, const std::string& advance_to)
throw game::game_error("Could not find the unit being advanced"
" to: " + advance_to);
}
unit_ptr new_unit(new unit(u));
unit_ptr new_unit = unit::create(u);
new_unit->set_experience(new_unit->experience_overflow());
new_unit->advance_to(*new_type);
new_unit->heal_fully();
@ -302,7 +302,7 @@ unit_ptr get_advanced_unit(const unit &u, const std::string& advance_to)
*/
unit_ptr get_amla_unit(const unit &u, const config &mod_option)
{
unit_ptr amla_unit(new unit(u));
unit_ptr amla_unit = unit::create(u);
amla_unit->set_experience(amla_unit->experience_overflow());
amla_unit->add_modification("advancement", mod_option);
return amla_unit;

View file

@ -1318,7 +1318,7 @@ void attack::unit_killed(unit_info& attacker,
if(const unit_type* reanimator = unit_types.find(attacker_stats->plague_type)) {
LOG_NG << "found unit type:" << reanimator->id() << '\n';
unit_ptr newunit(new unit(*reanimator, attacker.get_unit().side(), true, unit_race::MALE));
unit_ptr newunit = unit::create(*reanimator, attacker.get_unit().side(), true, unit_race::MALE);
newunit->set_attacks(0);
newunit->set_movement(0, true);
newunit->set_facing(map_location::get_opposite_dir(attacker.get_unit().facing()));

View file

@ -708,7 +708,7 @@ place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_locat
void recruit_unit(const unit_type & u_type, int side_num, const map_location & loc,
const map_location & from, bool show, bool use_undo)
{
const unit_ptr new_unit = unit_ptr( new unit(u_type, side_num, true));
const unit_ptr new_unit = unit::create(u_type, side_num, true);
// Place the recruit.

View file

@ -182,7 +182,7 @@ void unit_creator::add_unit(const config &cfg, const vconfig* vcfg)
if ( !recall_list_element ) {
//make the new unit
unit_ptr new_unit(new unit(temp_cfg, true, vcfg));
unit_ptr new_unit = unit::create(temp_cfg, true, vcfg);
map_location loc = find_location(temp_cfg, new_unit.get());
if ( loc.valid() ) {
//add the new unit to map

View file

@ -180,7 +180,7 @@ public:
, bound_unit_()
{
map_location loc(cfg["unit_x"], cfg["unit_y"], wml_loc()); // lua and c++ coords differ by one
bound_unit_.reset(new unit(*resources::gameboard->units().find(loc)));
bound_unit_ = unit::create(*resources::gameboard->units().find(loc));
}
virtual double evaluate()

View file

@ -144,8 +144,8 @@ bool simulated_recall(int side, const std::string& unit_id, const map_location&
bool simulated_recruit(int side, const unit_type* u, const map_location& recruit_location){
LOG_AI_SIM_ACTIONS << "Simulated recruit" << std::endl;
const unit recruit_unit(*u, side, false); // Random traits, name and gender are not needed. This will cause "duplicate id conflicts" inside unit_map::insert(), but engine will manage this issue correctly.
helper_place_unit(recruit_unit, recruit_location);
unit_ptr recruit_unit = unit::create(*u, side, false); // Random traits, name and gender are not needed. This will cause "duplicate id conflicts" inside unit_map::insert(), but engine will manage this issue correctly.
helper_place_unit(*recruit_unit, recruit_location);
resources::gameboard->get_team(side).spend_gold(u->cost());
@ -215,7 +215,7 @@ void helper_check_village(const map_location& loc, int side){
}
void helper_place_unit(const unit& u, const map_location& loc){
unit_ptr new_unit(new unit(u));
unit_ptr new_unit = unit::create(u);
new_unit->set_movement(0, true);
new_unit->set_attacks(0);
new_unit->heal_fully();
@ -248,7 +248,7 @@ void helper_advance_unit(const map_location& loc){
int options_num = unit_helper::number_of_possible_advances(*advance_unit);
size_t advance_choice = randomness::generator->get_random_int(0, options_num-1);
unit_ptr advanced_unit(new unit(*advance_unit));
unit_ptr advanced_unit = unit::create(*advance_unit);
if(advance_choice < options.size()){
std::string advance_unit_typename = options[advance_choice];

View file

@ -40,7 +40,7 @@ editor_action* editor_action_unit::perform(map_context& mc) const
void editor_action_unit::perform_without_undo(map_context& mc) const
{
mc.units().add(loc_, u_);
mc.units().add(loc_, *u_);
mc.units().find(loc_)->set_location(loc_);
mc.add_changed_location(loc_);
}

View file

@ -39,7 +39,7 @@ class editor_action_unit : public editor_action_location
public:
editor_action_unit(map_location loc, const unit& u)
: editor_action_location(loc)
, u_(u)
, u_(unit::create(u))
{
}
@ -54,7 +54,7 @@ public:
const std::string& get_name() const;
protected:
unit u_;
unit_ptr u_;
};
/**

View file

@ -122,8 +122,8 @@ editor_action* mouse_action_unit::up_left(editor_display& disp, int x, int y)
const unit_type &ut = *new_unit_type;
unit_race::GENDER gender = ut.genders().front();
unit new_unit(ut, disp.viewing_side(), true, gender);
editor_action* action = new editor_action_unit(hex, new_unit);
unit_ptr new_unit = unit::create(ut, disp.viewing_side(), true, gender);
editor_action* action = new editor_action_unit(hex, *new_unit);
return action;
}

View file

@ -362,7 +362,7 @@ void map_context::load_scenario(const config& game_config)
map_location loc(a_unit, nullptr);
a_unit["side"] = i;
units_.add(loc, unit(a_unit, true));
units_.add(loc, *unit::create(a_unit, true));
}
++i;

View file

@ -118,7 +118,7 @@ namespace { // Support functions
unit_race::GENDER gender = string_gender(cfg["gender"]);
const unit_type *ut = unit_types.find(type);
if (!ut) return fake_unit_ptr();
fake_unit_ptr fake = fake_unit_ptr(unit_ptr(new unit(*ut, side_num, false, gender)));
fake_unit_ptr fake = fake_unit_ptr(unit::create(*ut, side_num, false, gender));
if(!variation.empty()) {
config mod;
@ -920,12 +920,12 @@ WML_HANDLER_FUNCTION(unit,, cfg)
if (!to_variable.blank())
{
parsed_cfg.remove_attribute("to_variable");
unit new_unit(parsed_cfg, true, &cfg);
unit_ptr new_unit = unit::create(parsed_cfg, true, &cfg);
try
{
config &var = resources::gamedata->get_variable_cfg(to_variable);
var.clear();
new_unit.write(var);
new_unit->write(var);
if (const config::attribute_value *v = parsed_cfg.get("x")) var["x"] = *v;
if (const config::attribute_value *v = parsed_cfg.get("y")) var["y"] = *v;
}

View file

@ -935,9 +935,9 @@ void full_cost_map::add_unit(const map_location& origin, const unit_type* const
if (!ut) {
return;
}
unit u(*ut, side, false);
u.set_location(origin);
add_unit(u);
unit_ptr u = unit::create(*ut, side, false);
u->set_location(origin);
add_unit(*u);
}
/**

View file

@ -2107,7 +2107,7 @@ int game_lua_kernel::intf_put_unit(lua_State *L)
} else if (unit_arg != 1) {
deprecated_message("wesnoth.put_unit(x, y, unit)", DEP_LEVEL::FOR_REMOVAL, {1, 15, 0}, "Use wesnoth.put_unit(unit, x, y) or unit:to_map(x, y) instead.");
}
unit_ptr u(new unit(cfg, true, vcfg));
unit_ptr u = unit::create(cfg, true, vcfg);
put_unit_helper(loc);
u->set_location(loc);
units().insert(u);
@ -2187,7 +2187,7 @@ int game_lua_kernel::intf_put_recall_unit(lua_State *L)
} else {
const vconfig* vcfg = nullptr;
config cfg = luaW_checkconfig(L, 1, vcfg);
u = unit_ptr(new unit(cfg, true, vcfg));
u = unit::create(cfg, true, vcfg);
}
if (!side) {
@ -2228,7 +2228,7 @@ int game_lua_kernel::intf_extract_unit(lua_State *L)
u->anim_comp().clear_haloes();
} else if (int side = lu->on_recall_list()) {
team &t = board().get_team(side);
unit_ptr v = unit_ptr(new unit(*u));
unit_ptr v = unit::create(*u);
t.recall_list().erase_if_matches_id(u->id());
u = v;
} else {
@ -2257,7 +2257,7 @@ int game_lua_kernel::intf_find_vacant_tile(lua_State *L)
} else {
const vconfig* vcfg = nullptr;
config cfg = luaW_checkconfig(L, 2, vcfg);
u.reset(new unit(cfg, false, vcfg));
u = unit::create(cfg, false, vcfg);
}
}
@ -2300,7 +2300,7 @@ static int intf_create_unit(lua_State *L)
{
const vconfig* vcfg = nullptr;
config cfg = luaW_checkconfig(L, 1, vcfg);
unit_ptr u = unit_ptr(new unit(cfg, true, vcfg));
unit_ptr u = unit::create(cfg, true, vcfg);
luaW_pushunit(L, u);
return 1;
}
@ -2313,7 +2313,7 @@ static int intf_create_unit(lua_State *L)
static int intf_copy_unit(lua_State *L)
{
unit& u = luaW_checkunit(L, 1);
luaW_pushunit(L, unit_ptr(new unit(u)));
luaW_pushunit(L, unit::create(u));
return 1;
}

View file

@ -441,7 +441,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_unit, child, use_undo, /*show*/, /*error_
// Attempt to create a new unit. If there are error (such an invalid type key), exit.
try{
unit_ptr new_u(new unit(cfg, true));
unit_ptr new_u = unit::create(cfg, true);
new_u->set_location(loc);
// Don't remove the unit until after we've verified there are no errors in creating the new one,
// or else the unit would simply be removed from the map with no replacement.
@ -481,7 +481,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, use_undo, /*show*/, e
? resources::controller->current_side() : 1;
// Create the unit.
unit_ptr created(new unit(*u_type, side_num, true, gender));
unit_ptr created = unit::create(*u_type, side_num, true, gender);
created->new_turn();
unit_map::unit_iterator unit_it;

View file

@ -204,7 +204,7 @@ protected:
//seen before
config u_tmp = u;
u_tmp["side"] = std::to_string(side_);
t_->recall_list().add(unit_ptr(new unit(u_tmp,true)));
t_->recall_list().add(unit::create(u_tmp,true));
} else {
//not seen before
unit_configs_.push_back(&u);

View file

@ -35,8 +35,8 @@ BOOST_AUTO_TEST_CASE( test_1 ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit_ptr orc1(new unit(orc_type, 1, false));
unit_ptr orc2(new unit(orc_type, 1, false));
unit_ptr orc1 = unit::create(orc_type, 1, false);
unit_ptr orc2 = unit::create(orc_type, 1, false);
orc1->set_name("Larry");
orc2->set_name("Moe");

View file

@ -44,31 +44,31 @@ BOOST_AUTO_TEST_CASE( test_1 ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit orc1_side0_real(orc_type, 0, false);
unit orc2_side0_fake(orc_type, 0, false);
unit_ptr orc1_side0_real = unit::create(orc_type, 0, false);
unit_ptr orc2_side0_fake = unit::create(orc_type, 0, false);
unit_map unit_map;
typedef std::pair<unit_map::unit_iterator, bool> t_uresult;
t_uresult uresult1 = unit_map.add(map_location(1,1), orc1_side0_real);
t_uresult uresult1 = unit_map.add(map_location(1,1), *orc1_side0_real);
BOOST_CHECK_MESSAGE(uresult1.second == true, "Good Add");
BOOST_CHECK_EQUAL(unit_map.size(), 1);
unit_map::unit_iterator ui = unit_map.find(map_location(1,1));
BOOST_CHECK_MESSAGE(uresult1.first == ui, "Good Add");
BOOST_CHECK_MESSAGE(ui->underlying_id() == orc1_side0_real.underlying_id(), "Found Orc1");
BOOST_CHECK_MESSAGE(ui->underlying_id() == orc1_side0_real->underlying_id(), "Found Orc1");
unit_map::unit_iterator ui2 = unit_map.find(map_location(1,2));
BOOST_CHECK_MESSAGE(ui2 == unit_map.end(), "Not Found Orc1");
ui2 = unit_map.find(orc1_side0_real.underlying_id()+1);
ui2 = unit_map.find(orc1_side0_real->underlying_id()+1);
BOOST_CHECK_MESSAGE(ui2 == unit_map.end(), "Not Found Orc1");
// unit * orc1p = new unit(orc1_side0_real);
lg::set_log_domain_severity("engine", lg::err().get_severity() - 1); // Don't log anything
lg::set_log_domain_severity("unit", lg::err());
uresult1 = unit_map.add(map_location(1,1), orc1_side0_real);
uresult1 = unit_map.add(map_location(1,1), *orc1_side0_real);
lg::set_log_domain_severity("unit", lg::warn());
lg::set_log_domain_severity("engine", lg::info());
BOOST_CHECK_EQUAL(unit_map.size(), 1);
@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE( test_1 ) {
lg::set_log_domain_severity("engine", lg::err().get_severity() - 1); // Don't log anything
// If the location is invalid, the unit never needs to be cloned, so no warning is emitted in the unit domain
uresult1 = unit_map.add(map_location(-1,1), orc1_side0_real);
uresult1 = unit_map.add(map_location(-1,1), *orc1_side0_real);
lg::set_log_domain_severity("engine", lg::info());
BOOST_CHECK_EQUAL(unit_map.size(), 1);
BOOST_CHECK_MESSAGE(uresult1.second == false, "Didn't Add at invalid location.");
@ -89,13 +89,13 @@ BOOST_AUTO_TEST_CASE( test_1 ) {
lg::set_log_domain_severity("engine", lg::err().get_severity() - 1); // Don't log anything
lg::set_log_domain_severity("unit", lg::err());
uresult1 = unit_map.add(map_location(1,2), orc1_side0_real);
uresult1 = unit_map.add(map_location(1,2), *orc1_side0_real);
lg::set_log_domain_severity("unit", lg::warn());
lg::set_log_domain_severity("engine", lg::info());
BOOST_CHECK_EQUAL(unit_map.size(), 2);
BOOST_CHECK_MESSAGE(uresult1.second == true, "Added in face of id collision.");
BOOST_CHECK_MESSAGE(uresult1.first != unit_map.end(), "Added in face of id collision.");
BOOST_CHECK_MESSAGE(uresult1.first->underlying_id() != orc1_side0_real.underlying_id(), "Found Orc1");
BOOST_CHECK_MESSAGE(uresult1.first->underlying_id() != orc1_side0_real->underlying_id(), "Found Orc1");
BOOST_CHECK_MESSAGE(!unit_map.end().valid(), "Hmm, unit_map.end() is valid for dereference...");
//To check that the collisions will cut off change the cutoff in unit_map.cpp from 1e6 to less than the guard value below
@ -130,22 +130,22 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_underlying_id ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit orc1_side0_real(orc_type, 0, true);
unit_ptr orc1_side0_real = unit::create(orc_type, 0, true);
size_t underlying_id = orc1_side0_real.underlying_id();
size_t underlying_id = orc1_side0_real->underlying_id();
map_location hex = map_location(1,1);
unit_map unit_map;
typedef std::pair<unit_map::unit_iterator, bool> t_uresult;
t_uresult uresult1 = unit_map.add(hex, orc1_side0_real);
t_uresult uresult1 = unit_map.add(hex, *orc1_side0_real);
BOOST_CHECK(uresult1.second == true);
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
BOOST_CHECK(uresult1.first == ui);
BOOST_CHECK(ui->underlying_id() == orc1_side0_real.underlying_id());
BOOST_CHECK(ui->underlying_id() == orc1_side0_real->underlying_id());
}
unit_ptr extracted_unit = unit_map.extract(hex);
@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_underlying_id ) {
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
BOOST_CHECK(uresult1.first == ui);
BOOST_CHECK(ui->underlying_id() == orc1_side0_real.underlying_id());
BOOST_CHECK(ui->underlying_id() == orc1_side0_real->underlying_id());
}
}
@ -176,22 +176,22 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_underlying_id ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit orc1_side0_fake(orc_type, 0, false);
unit_ptr orc1_side0_fake = unit::create(orc_type, 0, false);
size_t underlying_id = orc1_side0_fake.underlying_id();
size_t underlying_id = orc1_side0_fake->underlying_id();
map_location hex = map_location(1,1);
unit_map unit_map;
typedef std::pair<unit_map::unit_iterator, bool> t_uresult;
t_uresult uresult1 = unit_map.add(hex, orc1_side0_fake);
t_uresult uresult1 = unit_map.add(hex, *orc1_side0_fake);
BOOST_CHECK(uresult1.second == true);
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
BOOST_CHECK(uresult1.first == ui);
BOOST_CHECK(ui->underlying_id() == orc1_side0_fake.underlying_id());
BOOST_CHECK(ui->underlying_id() == orc1_side0_fake->underlying_id());
}
unit_ptr extracted_unit = unit_map.extract(hex);
@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_underlying_id ) {
{
unit_map::unit_iterator ui = unit_map.find(underlying_id);
BOOST_CHECK(uresult1.first == ui);
BOOST_CHECK(ui->underlying_id() == orc1_side0_fake.underlying_id());
BOOST_CHECK(ui->underlying_id() == orc1_side0_fake->underlying_id());
}
}
@ -222,14 +222,14 @@ BOOST_AUTO_TEST_CASE( track_real_unit_by_iterator ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit orc1_side0_real(orc_type, 0, true);
unit_ptr orc1_side0_real = unit::create(orc_type, 0, true);
map_location hex = map_location(1,1);
unit_map unit_map;
typedef std::pair<unit_map::unit_iterator, bool> t_uresult;
t_uresult uresult1 = unit_map.add(hex, orc1_side0_real);
t_uresult uresult1 = unit_map.add(hex, *orc1_side0_real);
unit_map::unit_iterator unit_iterator = uresult1.first;
@ -259,14 +259,14 @@ BOOST_AUTO_TEST_CASE( track_fake_unit_by_iterator ) {
unit_types.build_unit_type(orc_type, unit_type::FULL);
unit orc1_side0_fake(orc_type, 0, false);
unit_ptr orc1_side0_fake = unit::create(orc_type, 0, false);
map_location hex = map_location(1,1);
unit_map unit_map;
typedef std::pair<unit_map::unit_iterator, bool> t_uresult;
t_uresult uresult1 = unit_map.add(hex, orc1_side0_fake);
t_uresult uresult1 = unit_map.add(hex, *orc1_side0_fake);
unit_map::unit_iterator unit_iterator = uresult1.first;

View file

@ -15,12 +15,15 @@
#include "units/make.hpp"
#include "units/unit.hpp"
unit_ptr make_unit_ptr(const config& cfg, bool use_traits, const vconfig* vcfg){
return { new unit(cfg, use_traits, vcfg) };
unit_ptr make_unit_ptr(const config& cfg, bool use_traits, const vconfig* vcfg)
{
return unit::create(cfg, use_traits, vcfg);
}
unit_ptr make_unit_ptr(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender){
return { new unit(t, side, real_unit, gender) };
unit_ptr make_unit_ptr(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender)
{
return unit::create(t, side, real_unit, gender);
}
unit_ptr make_unit_ptr(const unit& u){
return { new unit(u) };
unit_ptr make_unit_ptr(const unit& u)
{
return unit::create(u);
}

View file

@ -19,6 +19,7 @@ class config;
class unit_type;
class vconfig;
//file to allow creating units without including unit.hpp
unit_ptr make_unit_ptr(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
unit_ptr make_unit_ptr(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS);
unit_ptr make_unit_ptr(const unit& u);

View file

@ -80,7 +80,7 @@ unit_map::umap_retval_pair_t unit_map::add(const map_location& l, const unit& u)
self_check();
// TODO: should this take a shared pointer to a unit rather than make a copy?
unit_ptr p = unit_ptr(new unit(u));
unit_ptr p = unit::create(u);
p->set_location(l);
unit_map::umap_retval_pair_t res(insert(p));

View file

@ -206,7 +206,7 @@ void unit_mover::replace_temporary(unit_ptr u)
was_hidden_ = u->get_hidden();
// Make our temporary unit mostly match u...
temp_unit_ptr_ = fake_unit_ptr(unit_ptr(new unit(*u)), resources::fake_units);
temp_unit_ptr_ = fake_unit_ptr(unit::create(*u), resources::fake_units);
// ... but keep the temporary unhidden and hide the original.
temp_unit_ptr_->set_hidden(false);

View file

@ -375,32 +375,32 @@ unit::unit(const unit& o)
}
}
unit::unit(const config& cfg, bool use_traits, const vconfig* vcfg)
unit::unit()
: ref_count_(0)
, loc_(cfg["x"], cfg["y"], wml_loc())
, loc_()
, advances_to_()
, type_(&get_unit_type(cfg["parent_type"].blank() ? cfg["type"] : cfg["parent_type"]))
, type_(nullptr)
, type_name_()
, race_(&unit_race::null_race)
, id_(cfg["id"])
, name_(cfg["name"].t_str())
, id_()
, name_()
, underlying_id_(0)
, undead_variation_()
, variation_(cfg["variation"].empty() ? type_->default_variation() : cfg["variation"])
, variation_()
, hit_points_(1)
, max_hit_points_(0)
, max_hit_points_(1)
, experience_(0)
, max_experience_(0)
, max_experience_(1)
, level_(0)
, recall_cost_(-1)
, canrecruit_(cfg["canrecruit"].to_bool())
, canrecruit_(false)
, recruit_list_()
, alignment_()
, flag_rgb_()
, image_mods_()
, unrenamable_(false)
, side_(0)
, gender_(generate_gender(*type_, cfg))
, gender_(unit_race::NUM_GENDERS)
, formula_man_(new unit_formula_manager())
, movement_(0)
, max_movement_(0)
@ -419,7 +419,7 @@ unit::unit(const config& cfg, bool use_traits, const vconfig* vcfg)
, filter_recall_()
, emit_zoc_(0)
, overlays_()
, role_(cfg["role"])
, role_()
, attacks_()
, facing_(map_location::NDIRECTIONS)
, trait_names_()
@ -431,9 +431,9 @@ unit::unit(const config& cfg, bool use_traits, const vconfig* vcfg)
, is_healthy_(false)
, modification_descriptions_()
, anim_comp_(new unit_animation_component(*this))
, hidden_(cfg["hidden"].to_bool(false))
, hp_bar_scaling_(cfg["hp_bar_scaling"].blank() ? type_->hp_bar_scaling() : cfg["hp_bar_scaling"])
, xp_bar_scaling_(cfg["xp_bar_scaling"].blank() ? type_->xp_bar_scaling() : cfg["xp_bar_scaling"])
, hidden_(false)
, hp_bar_scaling_(0)
, xp_bar_scaling_(0)
, modifications_()
, abilities_()
, advancements_()
@ -443,10 +443,32 @@ unit::unit(const config& cfg, bool use_traits, const vconfig* vcfg)
, ellipse_()
, random_traits_(true)
, generate_name_(true)
, upkeep_()
, upkeep_(upkeep_full())
, invisibility_cache_()
{
side_ = cfg["side"];
}
void unit::init(const config& cfg, bool use_traits, const vconfig* vcfg)
{
loc_ = map_location(cfg["x"], cfg["y"], wml_loc());
type_ = &get_unit_type(cfg["parent_type"].blank() ? cfg["type"].str() : cfg["parent_type"].str());
race_ = &unit_race::null_race;
id_ = cfg["id"].str();
name_ = cfg["name"].t_str();
variation_ = cfg["variation"].empty() ? type_->default_variation() : cfg["variation"].str();
canrecruit_ = cfg["canrecruit"].to_bool();
gender_ = generate_gender(*type_, cfg);
role_ = cfg["role"].str();
//, facing_(map_location::NDIRECTIONS)
//, anim_comp_(new unit_animation_component(*this))
hidden_ = cfg["hidden"].to_bool(false);
hp_bar_scaling_ = cfg["hp_bar_scaling"].blank() ? type_->hp_bar_scaling() : cfg["hp_bar_scaling"];
xp_bar_scaling_ = cfg["xp_bar_scaling"].blank() ? type_->xp_bar_scaling() : cfg["xp_bar_scaling"];
random_traits_ = true;
generate_name_ = true;
side_ = cfg["side"].to_int();
if(side_ <= 0) {
side_ = 1;
}
@ -669,74 +691,14 @@ void unit::clear_status_caches()
units_with_cache.clear();
}
unit::unit(const unit_type& u_type, int side, bool real_unit, unit_race::GENDER gender)
: ref_count_(0)
, loc_()
, advances_to_()
, type_(&u_type)
, type_name_()
, race_(&unit_race::null_race)
, id_()
, name_()
, undead_variation_()
, variation_(type_->default_variation())
, hit_points_(0)
, max_hit_points_(0)
, experience_(0)
, max_experience_(0)
, level_(0)
, recall_cost_(-1)
, canrecruit_(false)
, recruit_list_()
, alignment_()
, flag_rgb_()
, image_mods_()
, unrenamable_(false)
, side_(side)
, gender_(gender != unit_race::NUM_GENDERS ? gender : generate_gender(u_type, real_unit))
, formula_man_(new unit_formula_manager())
, movement_(0)
, max_movement_(0)
, vision_(-1)
, jamming_(0)
, movement_type_()
, hold_position_(false)
, end_turn_(false)
, resting_(false)
, attacks_left_(0)
, max_attacks_(0)
, states_()
, known_boolean_states_()
, variables_()
, events_()
, filter_recall_()
, emit_zoc_(0)
, overlays_()
, role_()
, attacks_()
, facing_(static_cast<map_location::DIRECTION>(randomness::rng::default_instance().get_random_int(0, map_location::NDIRECTIONS-1)))
, trait_names_()
, trait_descriptions_()
, unit_value_()
, goto_()
, interrupted_move_()
, is_fearless_(false)
, is_healthy_(false)
, modification_descriptions_()
, anim_comp_(new unit_animation_component(*this))
, hidden_(false)
, modifications_()
, abilities_()
, advancements_()
, description_()
, usage_()
, halo_()
, ellipse_()
, random_traits_(true)
, generate_name_(true)
, upkeep_()
, invisibility_cache_()
{
void unit::init(const unit_type& u_type, int side, bool real_unit, unit_race::GENDER gender)
{
type_ = &u_type;
race_ = &unit_race::null_race;
variation_ = type_->default_variation();
side_ = side;
gender_ = gender != unit_race::NUM_GENDERS ? gender : generate_gender(u_type, real_unit);
facing_ = static_cast<map_location::DIRECTION>(randomness::rng::default_instance().get_random_int(0, map_location::NDIRECTIONS-1));
upkeep_ = upkeep_full();
// Apply the unit type's data to this unit.

View file

@ -108,20 +108,42 @@ public:
/** The path to the leader crown overlay. */
static const std::string& leader_crown();
private:
void init(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
void init(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS);
// Copy constructor
unit(const unit& u);
unit();
public:
/** Initializes a unit from a config */
unit(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr);
static unit_ptr create(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr)
{
unit_ptr res(new unit());
res->init(cfg, use_traits, vcfg);
return res;
}
/**
* Initializes a unit from a unit type.
*
* Only real_unit-s should have random traits, name and gender (to prevent OOS caused by RNG calls)
*/
unit(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS);
// Copy constructor
unit(const unit& u);
static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS)
{
unit_ptr res(new unit());
res->init(t, side, real_unit, gender);
return res;
}
// maybe rename this to copy?
static unit_ptr create(const unit& u)
{
return unit_ptr(new unit(u));
}
virtual ~unit();
void swap(unit&);

View file

@ -726,7 +726,7 @@ void manager::create_temp_move()
if(!fake_unit || fake_unit.get_unit_ptr()->id() != temp_moved_unit->id())
{
// Create temp ghost unit
fake_unit = fake_unit_ptr(unit_ptr (new unit(*temp_moved_unit)), resources::fake_units);
fake_unit = fake_unit_ptr(unit::create(*temp_moved_unit), resources::fake_units);
fake_unit->anim_comp().set_ghosted(true);
}

View file

@ -132,7 +132,7 @@ move::move(const config& cfg, bool hidden)
arrow_->set_path(route_->steps);
// Construct fake_unit_
fake_unit_ = fake_unit_ptr( unit_ptr(new unit(*get_unit())) , resources::fake_units );
fake_unit_ = fake_unit_ptr(unit::create(*get_unit()) , resources::fake_units );
if(hidden)
fake_unit_->set_hidden(true);
fake_unit_->anim_comp().set_ghosted(true);

View file

@ -57,11 +57,11 @@ std::ostream& recall::print(std::ostream &s) const
return s;
}
recall::recall(size_t team_index, bool hidden, const unit& unit, const map_location& recall_hex):
recall::recall(size_t team_index, bool hidden, const unit& u, const map_location& recall_hex):
action(team_index,hidden),
temp_unit_(new class unit(unit)),
temp_unit_(unit::create(u)),
recall_hex_(recall_hex),
fake_unit_(unit_ptr( new class unit(unit) ) )
fake_unit_(unit::create(u))
{
this->init();
}
@ -78,7 +78,7 @@ recall::recall(const config& cfg, bool hidden)
{
if(recall_unit->underlying_id()==underlying_id)
{
temp_unit_.reset(new class unit(*recall_unit)); //TODO: is it necessary to make a copy?
temp_unit_ = unit::create(*recall_unit); //TODO: is it necessary to make a copy?
break;
}
}
@ -86,7 +86,7 @@ recall::recall(const config& cfg, bool hidden)
throw action::ctor_err("recall: Invalid underlying_id");
}
fake_unit_.reset(unit_ptr(new class unit(*temp_unit_))); //makes copy of temp_unit_
fake_unit_.reset(unit::create(*temp_unit_)); //makes copy of temp_unit_
this->init();
}

View file

@ -58,7 +58,7 @@ recruit::recruit(size_t team_index, bool hidden, const std::string& unit_name, c
unit_name_(unit_name),
recruit_hex_(recruit_hex),
temp_unit_(create_corresponding_unit()), //auto-ptr ownership transfer
fake_unit_(unit_ptr(new unit(*temp_unit_))), //temp_unit_ *copied* into new fake unit
fake_unit_(unit::create(*temp_unit_)), //temp_unit_ *copied* into new fake unit
cost_(0)
{
this->init();
@ -78,7 +78,7 @@ recruit::recruit(const config& cfg, bool hidden)
// Construct temp_unit_ and fake_unit_
temp_unit_ = create_corresponding_unit(); //auto-ptr ownership transfer
fake_unit_.reset(unit_ptr (new unit(*temp_unit_))), //temp_unit_ copied into new fake_unit
fake_unit_.reset(unit::create(*temp_unit_)); //temp_unit_ copied into new fake_unit
this->init();
}
@ -173,7 +173,7 @@ unit_ptr recruit::create_corresponding_unit()
int side_num = team_index() + 1;
//real_unit = false needed to avoid generating random traits and causing OOS
bool real_unit = false;
unit_ptr result(new unit(*type, side_num, real_unit));
unit_ptr result = unit::create(*type, side_num, real_unit);
result->set_movement(0, true);
result->set_attacks(0);
return result; //ownership gets transferred to returned unique_ptr copy