use shared_ptr for unit_ptr (#4985)
use shared_ptr for unit_ptr This make the code a bit simpler, furthermore it allows us to use weak_ptr to unit should we ever need that. Furthermore this adds a class shared_reference that wraps shared_ptr but can never be nullptr.
This commit is contained in:
parent
f33330de19
commit
6d73033445
23 changed files with 288 additions and 187 deletions
|
@ -124,7 +124,7 @@ namespace
|
|||
if (animate && !CVideo::get_singleton().update_locked()) {
|
||||
unit_animator animator;
|
||||
bool with_bars = true;
|
||||
animator.add_animation(&*u, "levelout", u->get_location(), map_location(), 0, with_bars);
|
||||
animator.add_animation(u.get_shared_ptr(), "levelout", u->get_location(), map_location(), 0, with_bars);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ namespace
|
|||
|
||||
if (animate && u != resources::gameboard->units().end() && !CVideo::get_singleton().update_locked()) {
|
||||
unit_animator animator;
|
||||
animator.add_animation(&*u, "levelin", u->get_location(), map_location(), 0, true);
|
||||
animator.add_animation(u.get_shared_ptr(), "levelin", u->get_location(), map_location(), 0, true);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
animator.set_all_standing();
|
||||
|
|
|
@ -72,19 +72,19 @@ static lg::log_domain log_config("config");
|
|||
// BATTLE CONTEXT UNIT STATS
|
||||
// ==================================================================================
|
||||
|
||||
battle_context_unit_stats::battle_context_unit_stats(const unit& u,
|
||||
battle_context_unit_stats::battle_context_unit_stats(nonempty_unit_const_ptr up,
|
||||
const map_location& u_loc,
|
||||
int u_attack_num,
|
||||
bool attacking,
|
||||
const unit& opp,
|
||||
nonempty_unit_const_ptr oppp,
|
||||
const map_location& opp_loc,
|
||||
const_attack_ptr opp_weapon,
|
||||
const unit_map& units)
|
||||
: weapon(nullptr)
|
||||
, attack_num(u_attack_num)
|
||||
, is_attacker(attacking)
|
||||
, is_poisoned(u.get_state(unit::STATE_POISONED))
|
||||
, is_slowed(u.get_state(unit::STATE_SLOWED))
|
||||
, is_poisoned(up->get_state(unit::STATE_POISONED))
|
||||
, is_slowed(up->get_state(unit::STATE_SLOWED))
|
||||
, slows(false)
|
||||
, drains(false)
|
||||
, petrifies(false)
|
||||
|
@ -94,12 +94,12 @@ battle_context_unit_stats::battle_context_unit_stats(const unit& u,
|
|||
, swarm(false)
|
||||
, firststrike(false)
|
||||
, disable(false)
|
||||
, experience(u.experience())
|
||||
, max_experience(u.max_experience())
|
||||
, level(u.level())
|
||||
, experience(up->experience())
|
||||
, max_experience(up->max_experience())
|
||||
, level(up->level())
|
||||
, rounds(1)
|
||||
, hp(0)
|
||||
, max_hp(u.max_hitpoints())
|
||||
, max_hp(up->max_hitpoints())
|
||||
, chance_to_hit(0)
|
||||
, damage(0)
|
||||
, slow_damage(0)
|
||||
|
@ -110,6 +110,8 @@ battle_context_unit_stats::battle_context_unit_stats(const unit& u,
|
|||
, swarm_max(0)
|
||||
, plague_type()
|
||||
{
|
||||
const unit& u = *up;
|
||||
const unit& opp = *oppp;
|
||||
// Get the current state of the unit.
|
||||
if(attack_num >= 0) {
|
||||
weapon = u.attacks()[attack_num].shared_from_this();
|
||||
|
@ -132,11 +134,11 @@ battle_context_unit_stats::battle_context_unit_stats(const unit& u,
|
|||
}
|
||||
|
||||
// Get the weapon characteristics as appropriate.
|
||||
auto ctx = weapon->specials_context(&u, &opp, u_loc, opp_loc, attacking, opp_weapon);
|
||||
auto ctx = weapon->specials_context(up, oppp, u_loc, opp_loc, attacking, opp_weapon);
|
||||
boost::optional<decltype(ctx)> opp_ctx;
|
||||
|
||||
if(opp_weapon) {
|
||||
opp_ctx.emplace(opp_weapon->specials_context(&opp, &u, opp_loc, u_loc, !attacking, weapon));
|
||||
opp_ctx.emplace(opp_weapon->specials_context(oppp, up, opp_loc, u_loc, !attacking, weapon));
|
||||
}
|
||||
|
||||
slows = weapon->bool_ability("slow");
|
||||
|
@ -365,10 +367,10 @@ battle_context_unit_stats::battle_context_unit_stats(const unit_type* u_type,
|
|||
// ==================================================================================
|
||||
|
||||
battle_context::battle_context(
|
||||
const unit& attacker,
|
||||
nonempty_unit_const_ptr attacker,
|
||||
const map_location& a_loc,
|
||||
int a_wep_index,
|
||||
const unit& defender,
|
||||
nonempty_unit_const_ptr defender,
|
||||
const map_location& d_loc,
|
||||
int d_wep_index,
|
||||
const unit_map& units)
|
||||
|
@ -380,8 +382,8 @@ battle_context::battle_context(
|
|||
size_t a_wep_uindex = static_cast<size_t>(a_wep_index);
|
||||
size_t d_wep_uindex = static_cast<size_t>(d_wep_index);
|
||||
|
||||
const_attack_ptr a_wep(a_wep_uindex < attacker.attacks().size() ? attacker.attacks()[a_wep_index].shared_from_this() : nullptr);
|
||||
const_attack_ptr d_wep(d_wep_uindex < defender.attacks().size() ? defender.attacks()[d_wep_index].shared_from_this() : nullptr);
|
||||
const_attack_ptr a_wep(a_wep_uindex < attacker->attacks().size() ? attacker->attacks()[a_wep_index].shared_from_this() : nullptr);
|
||||
const_attack_ptr d_wep(d_wep_uindex < defender->attacks().size() ? defender->attacks()[d_wep_index].shared_from_this() : nullptr);
|
||||
|
||||
attacker_stats_.reset(new battle_context_unit_stats(attacker, a_loc, a_wep_index, true , defender, d_loc, d_wep, units));
|
||||
defender_stats_.reset(new battle_context_unit_stats(defender, d_loc, d_wep_index, false, attacker, a_loc, a_wep, units));
|
||||
|
@ -407,30 +409,37 @@ battle_context::battle_context(const unit_map& units,
|
|||
int defender_weapon,
|
||||
double aggression,
|
||||
const combatant* prev_def,
|
||||
const unit* attacker_ptr,
|
||||
const unit* defender_ptr)
|
||||
unit_const_ptr attacker,
|
||||
unit_const_ptr defender)
|
||||
: attacker_stats_(nullptr)
|
||||
, defender_stats_(nullptr)
|
||||
, attacker_combatant_(nullptr)
|
||||
, defender_combatant_(nullptr)
|
||||
{
|
||||
//TODO: maybe check before dereferencing units.find(attacker_loc),units.find(defender_loc) ?
|
||||
const unit& attacker = attacker_ptr ? *attacker_ptr : *units.find(attacker_loc);
|
||||
const unit& defender = defender_ptr ? *defender_ptr : *units.find(defender_loc);
|
||||
if(!attacker) {
|
||||
attacker = units.find(attacker_loc).get_shared_ptr();
|
||||
}
|
||||
if(!defender) {
|
||||
defender = units.find(defender_loc).get_shared_ptr();
|
||||
}
|
||||
nonempty_unit_const_ptr n_attacker { attacker };
|
||||
nonempty_unit_const_ptr n_defender { defender };
|
||||
|
||||
const double harm_weight = 1.0 - aggression;
|
||||
|
||||
if(attacker_weapon == -1) {
|
||||
*this = choose_attacker_weapon(
|
||||
attacker, defender, units, attacker_loc, defender_loc, harm_weight, prev_def
|
||||
n_attacker, n_defender, units, attacker_loc, defender_loc, harm_weight, prev_def
|
||||
);
|
||||
}
|
||||
else if(defender_weapon == -1) {
|
||||
*this = choose_defender_weapon(
|
||||
attacker, defender, attacker_weapon, units, attacker_loc, defender_loc, prev_def
|
||||
n_attacker, n_defender, attacker_weapon, units, attacker_loc, defender_loc, prev_def
|
||||
);
|
||||
}
|
||||
else {
|
||||
*this = battle_context(attacker, attacker_loc, attacker_weapon, defender, defender_loc, defender_weapon, units);
|
||||
*this = battle_context(n_attacker, attacker_loc, attacker_weapon, n_defender, defender_loc, defender_weapon, units);
|
||||
}
|
||||
|
||||
assert(attacker_stats_);
|
||||
|
@ -529,8 +538,8 @@ bool battle_context::better_combat(const combatant& us_a,
|
|||
return them_a.average_hp() < them_b.average_hp();
|
||||
}
|
||||
|
||||
battle_context battle_context::choose_attacker_weapon(const unit& attacker,
|
||||
const unit& defender,
|
||||
battle_context battle_context::choose_attacker_weapon(nonempty_unit_const_ptr attacker,
|
||||
nonempty_unit_const_ptr defender,
|
||||
const unit_map& units,
|
||||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
|
@ -541,8 +550,8 @@ battle_context battle_context::choose_attacker_weapon(const unit& attacker,
|
|||
std::vector<battle_context> choices;
|
||||
|
||||
// What options does attacker have?
|
||||
for(size_t i = 0; i < attacker.attacks().size(); ++i) {
|
||||
const attack_type& att = attacker.attacks()[i];
|
||||
for(size_t i = 0; i < attacker->attacks().size(); ++i) {
|
||||
const attack_type& att = attacker->attacks()[i];
|
||||
|
||||
if(att.attack_weight() <= 0) {
|
||||
continue;
|
||||
|
@ -583,8 +592,8 @@ battle_context battle_context::choose_attacker_weapon(const unit& attacker,
|
|||
}
|
||||
|
||||
/** @todo FIXME: Hand previous defender unit in here. */
|
||||
battle_context battle_context::choose_defender_weapon(const unit& attacker,
|
||||
const unit& defender,
|
||||
battle_context battle_context::choose_defender_weapon(nonempty_unit_const_ptr attacker,
|
||||
nonempty_unit_const_ptr defender,
|
||||
unsigned attacker_weapon,
|
||||
const unit_map& units,
|
||||
const map_location& attacker_loc,
|
||||
|
@ -592,15 +601,15 @@ battle_context battle_context::choose_defender_weapon(const unit& attacker,
|
|||
const combatant* prev_def)
|
||||
{
|
||||
log_scope2(log_attack, "choose_defender_weapon");
|
||||
VALIDATE(attacker_weapon < attacker.attacks().size(), _("An invalid attacker weapon got selected."));
|
||||
VALIDATE(attacker_weapon < attacker->attacks().size(), _("An invalid attacker weapon got selected."));
|
||||
|
||||
const attack_type& att = attacker.attacks()[attacker_weapon];
|
||||
const attack_type& att = attacker->attacks()[attacker_weapon];
|
||||
auto no_weapon = [&]() { return battle_context(attacker, attacker_loc, attacker_weapon, defender, defender_loc, -1, units); };
|
||||
std::vector<battle_context> choices;
|
||||
|
||||
// What options does defender have?
|
||||
for(size_t i = 0; i < defender.attacks().size(); ++i) {
|
||||
const attack_type& def = defender.attacks()[i];
|
||||
for(size_t i = 0; i < defender->attacks().size(); ++i) {
|
||||
const attack_type& def = defender->attacks()[i];
|
||||
if(def.range() != att.range() || def.defense_weight() <= 0) {
|
||||
//no need to calculate the battle_context here.
|
||||
continue;
|
||||
|
@ -636,7 +645,7 @@ battle_context battle_context::choose_defender_weapon(const unit& attacker,
|
|||
double max_weight = 0.0;
|
||||
|
||||
for(const auto& choice : choices) {
|
||||
const attack_type& def = defender.attacks()[choice.defender_stats_->attack_num];
|
||||
const attack_type& def = defender->attacks()[choice.defender_stats_->attack_num];
|
||||
|
||||
if(def.defense_weight() >= max_weight) {
|
||||
const battle_context_unit_stats& def_stats = *choice.defender_stats_;
|
||||
|
@ -655,7 +664,7 @@ battle_context battle_context::choose_defender_weapon(const unit& attacker,
|
|||
battle_context* best_choice = nullptr;
|
||||
// Multiple options: simulate them, save best.
|
||||
for(auto& choice : choices) {
|
||||
const attack_type& def = defender.attacks()[choice.defender_stats_->attack_num];
|
||||
const attack_type& def = defender->attacks()[choice.defender_stats_->attack_num];
|
||||
|
||||
choice.simulate(prev_def);
|
||||
|
||||
|
@ -744,6 +753,7 @@ private:
|
|||
|
||||
unit_info(const map_location& loc, int weapon, unit_map& units);
|
||||
unit& get_unit();
|
||||
unit_ptr get_unit_ptr();
|
||||
bool valid();
|
||||
|
||||
std::string dump();
|
||||
|
@ -807,6 +817,15 @@ unit& attack::unit_info::get_unit()
|
|||
return *i;
|
||||
}
|
||||
|
||||
unit_ptr attack::unit_info::get_unit_ptr()
|
||||
{
|
||||
unit_map::iterator i = units_.find(loc_);
|
||||
if(i.valid() && i->underlying_id() == id_) {
|
||||
return i.get_shared_ptr();
|
||||
}
|
||||
return unit_ptr();
|
||||
}
|
||||
|
||||
bool attack::unit_info::valid()
|
||||
{
|
||||
unit_map::iterator i = units_.find(loc_);
|
||||
|
@ -1261,7 +1280,7 @@ void attack::unit_killed(unit_info& attacker,
|
|||
attacker_stats->weapon,
|
||||
defender_stats->weapon,
|
||||
attacker.loc_,
|
||||
&attacker.get_unit()
|
||||
attacker.get_unit_ptr()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1400,7 +1419,7 @@ void attack::perform()
|
|||
<< (defender_strikes_first ? " defender first-strike" : "") << "\n";
|
||||
|
||||
// Play the pre-fight animation
|
||||
unit_display::unit_draw_weapon(a_.loc_, a_.get_unit(), a_stats_->weapon, d_stats_->weapon, d_.loc_, &d_.get_unit());
|
||||
unit_display::unit_draw_weapon(a_.loc_, a_.get_unit(), a_stats_->weapon, d_stats_->weapon, d_.loc_, d_.get_unit_ptr());
|
||||
|
||||
for(;;) {
|
||||
DBG_NG << "start of attack loop...\n";
|
||||
|
@ -1464,8 +1483,8 @@ void attack::perform()
|
|||
u.set_experience(u.experience() + d_.xp_);
|
||||
}
|
||||
|
||||
unit_display::unit_sheath_weapon(a_.loc_, a_.valid() ? &a_.get_unit() : nullptr, a_stats_->weapon, d_stats_->weapon,
|
||||
d_.loc_, d_.valid() ? &d_.get_unit() : nullptr);
|
||||
unit_display::unit_sheath_weapon(a_.loc_, a_.get_unit_ptr(), a_stats_->weapon, d_stats_->weapon,
|
||||
d_.loc_, d_.get_unit_ptr());
|
||||
|
||||
if(update_display_) {
|
||||
game_display::get_singleton()->invalidate_unit();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "ai/lua/aspect_advancements.hpp"
|
||||
#include "attack_prediction.hpp"
|
||||
#include "units/alignment.hpp"
|
||||
#include "units/ptr.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -82,11 +83,11 @@ struct battle_context_unit_stats
|
|||
|
||||
std::string plague_type; /**< The plague type used by the attack, if any. */
|
||||
|
||||
battle_context_unit_stats(const unit& u,
|
||||
battle_context_unit_stats(nonempty_unit_const_ptr u,
|
||||
const map_location& u_loc,
|
||||
int u_attack_num,
|
||||
bool attacking,
|
||||
const unit& opp,
|
||||
nonempty_unit_const_ptr opp,
|
||||
const map_location& opp_loc,
|
||||
const_attack_ptr opp_weapon,
|
||||
const unit_map& units);
|
||||
|
@ -185,8 +186,8 @@ public:
|
|||
int defender_weapon = -1,
|
||||
double aggression = 0.0,
|
||||
const combatant* prev_def = nullptr,
|
||||
const unit* attacker_ptr = nullptr,
|
||||
const unit* defender_ptr = nullptr);
|
||||
unit_const_ptr attacker_ptr = unit_const_ptr(),
|
||||
unit_const_ptr defender_ptr = unit_const_ptr());
|
||||
|
||||
/** Used by the AI which caches battle_context_unit_stats */
|
||||
battle_context(const battle_context_unit_stats& att, const battle_context_unit_stats& def);
|
||||
|
@ -225,24 +226,24 @@ public:
|
|||
void simulate(const combatant* prev_def);
|
||||
private:
|
||||
battle_context(
|
||||
const unit& attacker,
|
||||
nonempty_unit_const_ptr attacker,
|
||||
const map_location& attacker_loc,
|
||||
int attacker_weapon,
|
||||
const unit& defender,
|
||||
nonempty_unit_const_ptr defender,
|
||||
const map_location& defender_loc,
|
||||
int defender_weapon,
|
||||
const unit_map& units);
|
||||
|
||||
static battle_context choose_attacker_weapon(const unit& attacker,
|
||||
const unit& defender,
|
||||
static battle_context choose_attacker_weapon(nonempty_unit_const_ptr attacker,
|
||||
nonempty_unit_const_ptr defender,
|
||||
const unit_map& units,
|
||||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
double harm_weight,
|
||||
const combatant* prev_def);
|
||||
|
||||
static battle_context choose_defender_weapon(const unit& attacker,
|
||||
const unit& defender,
|
||||
static battle_context choose_defender_weapon(nonempty_unit_const_ptr attacker,
|
||||
nonempty_unit_const_ptr defender,
|
||||
unsigned attacker_weapon,
|
||||
const unit_map& units,
|
||||
const map_location& attacker_loc,
|
||||
|
|
|
@ -162,7 +162,7 @@ attack_callable::attack_callable(const map_location& move_from,
|
|||
const map_location& src, const map_location& dst, int weapon)
|
||||
: move_from_(move_from), src_(src), dst_(dst),
|
||||
bc_(resources::gameboard->units(), src, dst, weapon, -1, 1.0, nullptr,
|
||||
&*resources::gameboard->units().find(move_from))
|
||||
resources::gameboard->units().find(move_from).get_shared_ptr())
|
||||
{
|
||||
type_ = ATTACK_C;
|
||||
}
|
||||
|
|
|
@ -617,7 +617,7 @@ DEFINE_WFL_FUNCTION(calculate_outcome, 3, 4)
|
|||
}
|
||||
|
||||
battle_context bc(units, args()[1]->evaluate(variables, add_debug_info(fdb, 1, "calculate_outcome:attacker_attack_location")).convert_to<location_callable>()->loc(),
|
||||
defender_location, weapon, -1, 1.0, nullptr, &*units.find(attacker_location));
|
||||
defender_location, weapon, -1, 1.0, nullptr, units.find(attacker_location).get_shared_ptr());
|
||||
std::vector<double> hp_dist = bc.get_attacker_combatant().hp_dist;
|
||||
std::vector<double>::iterator it = hp_dist.begin();
|
||||
int i = 0;
|
||||
|
|
|
@ -61,6 +61,16 @@ const unit * display_context::get_visible_unit(const map_location & loc, const t
|
|||
return &*u;
|
||||
}
|
||||
|
||||
unit_const_ptr display_context::get_visible_unit_shared_ptr(const map_location & loc, const team ¤t_team, bool see_all) const
|
||||
{
|
||||
if (!map().on_board(loc)) return nullptr;
|
||||
const unit_map::const_iterator u = units().find(loc);
|
||||
if (!u.valid() || !u->is_visible_to_team(current_team, see_all)) {
|
||||
return unit_const_ptr();
|
||||
}
|
||||
return u.get_shared_ptr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return true iff the unit @a u has any possible moves
|
||||
* it can do (including attacking etc).
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "units/ptr.hpp"
|
||||
|
||||
class team;
|
||||
class gamemap;
|
||||
|
@ -60,6 +61,7 @@ public:
|
|||
// Needed for reports
|
||||
|
||||
const unit * get_visible_unit(const map_location &loc, const team ¤t_team, bool see_all = false) const;
|
||||
unit_const_ptr get_visible_unit_shared_ptr(const map_location &loc, const team ¤t_team, bool see_all = false) const;
|
||||
|
||||
// From actions:: namespace
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ const unsigned int attack_predictions::graph_width = 270;
|
|||
const unsigned int attack_predictions::graph_height = 170;
|
||||
const unsigned int attack_predictions::graph_max_rows = 10;
|
||||
|
||||
attack_predictions::attack_predictions(battle_context& bc, const unit& attacker, const unit& defender)
|
||||
attack_predictions::attack_predictions(battle_context& bc, unit_const_ptr attacker, unit_const_ptr defender)
|
||||
: attacker_data_(attacker, bc.get_attacker_combatant(), bc.get_attacker_stats())
|
||||
, defender_data_(defender, bc.get_defender_combatant(), bc.get_defender_stats())
|
||||
{
|
||||
|
@ -127,11 +127,11 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
|
||||
// Set specials context (for safety, it should not have changed normally).
|
||||
const_attack_ptr weapon = attacker.stats_.weapon, opp_weapon = defender.stats_.weapon;
|
||||
auto ctx = weapon->specials_context(&attacker.unit_, &defender.unit_, attacker.unit_.get_location(), defender.unit_.get_location(), attacker.stats_.is_attacker, opp_weapon);
|
||||
auto ctx = weapon->specials_context(attacker.unit_, defender.unit_, attacker.unit_->get_location(), defender.unit_->get_location(), attacker.stats_.is_attacker, opp_weapon);
|
||||
boost::optional<decltype(ctx)> opp_ctx;
|
||||
|
||||
if(opp_weapon) {
|
||||
opp_ctx.emplace(opp_weapon->specials_context(&defender.unit_, &attacker.unit_, defender.unit_.get_location(), attacker.unit_.get_location(), defender.stats_.is_attacker, weapon));
|
||||
opp_ctx.emplace(opp_weapon->specials_context(defender.unit_, attacker.unit_, defender.unit_->get_location(), attacker.unit_->get_location(), defender.stats_.is_attacker, weapon));
|
||||
}
|
||||
|
||||
// Get damage modifiers.
|
||||
|
@ -187,7 +187,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
ss.str("");
|
||||
|
||||
// Resistance modifier.
|
||||
const int resistance_modifier = defender.unit_.damage_from(*weapon, !attacker.stats_.is_attacker, defender.unit_.get_location(), opp_weapon);
|
||||
const int resistance_modifier = defender.unit_->damage_from(*weapon, !attacker.stats_.is_attacker, defender.unit_->get_location(), opp_weapon);
|
||||
if(resistance_modifier != 100) {
|
||||
if(attacker.stats_.is_attacker) {
|
||||
if(resistance_modifier < 100) {
|
||||
|
@ -218,7 +218,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
// TODO: color format the modifiers
|
||||
|
||||
// Time of day modifier.
|
||||
const unit& u = attacker.unit_;
|
||||
const unit& u = *attacker.unit_;
|
||||
|
||||
const int tod_modifier = combat_modifier(resources::gameboard->units(), resources::gameboard->map(),
|
||||
u.get_location(), u.alignment(), u.is_fearless());
|
||||
|
@ -230,7 +230,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
}
|
||||
|
||||
// Leadership bonus.
|
||||
const int leadership_bonus = under_leadership(attacker.unit_, attacker.unit_.get_location(), weapon, opp_weapon);
|
||||
const int leadership_bonus = under_leadership(*attacker.unit_, attacker.unit_->get_location(), weapon, opp_weapon);
|
||||
|
||||
if(leadership_bonus != 0) {
|
||||
set_label_helper("leadership_modifier", utils::signed_percent(leadership_bonus));
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "actions/attack.hpp"
|
||||
#include "gui/dialogs/modal_dialog.hpp"
|
||||
#include "units/map.hpp"
|
||||
#include "units/ptr.hpp"
|
||||
|
||||
class battle_context;
|
||||
|
||||
|
@ -36,7 +36,7 @@ using hp_probability_vector = std::vector<hp_probability_t>;
|
|||
class attack_predictions : public modal_dialog
|
||||
{
|
||||
public:
|
||||
attack_predictions(battle_context& bc, const unit& attacker, const unit& defender);
|
||||
attack_predictions(battle_context& bc, unit_const_ptr attacker, unit_const_ptr defender);
|
||||
|
||||
DEFINE_SIMPLE_DISPLAY_WRAPPER(attack_predictions)
|
||||
|
||||
|
@ -49,7 +49,7 @@ private:
|
|||
|
||||
struct combatant_data
|
||||
{
|
||||
combatant_data(const unit& unit, const combatant& combatant, const battle_context_unit_stats& stats)
|
||||
combatant_data(unit_const_ptr unit, const combatant& combatant, const battle_context_unit_stats& stats)
|
||||
: stats_(stats)
|
||||
, combatant_(combatant)
|
||||
, unit_(unit)
|
||||
|
@ -57,7 +57,8 @@ private:
|
|||
|
||||
const battle_context_unit_stats& stats_;
|
||||
const combatant& combatant_;
|
||||
const unit& unit_;
|
||||
/// never null
|
||||
unit_const_ptr unit_;
|
||||
};
|
||||
|
||||
void set_data(window& window, const combatant_data& attacker, const combatant_data& defender);
|
||||
|
|
|
@ -84,7 +84,7 @@ unit_attack::unit_attack(const unit_map::iterator& attacker_itor,
|
|||
void unit_attack::damage_calc_callback(window& window)
|
||||
{
|
||||
const std::size_t index = find_widget<listbox>(&window, "weapon_list", false).get_selected_row();
|
||||
attack_predictions::display(weapons_[index], *attacker_itor_, *defender_itor_);
|
||||
attack_predictions::display(weapons_[index], attacker_itor_.get_shared_ptr(), defender_itor_.get_shared_ptr());
|
||||
}
|
||||
|
||||
void unit_attack::pre_show(window& window)
|
||||
|
|
|
@ -141,6 +141,13 @@ static const unit *get_selected_unit(reports::context & rc)
|
|||
rc.screen().show_everything());
|
||||
}
|
||||
|
||||
static unit_const_ptr get_selected_unit_ptr(reports::context & rc)
|
||||
{
|
||||
return rc.dc().get_visible_unit_shared_ptr(rc.screen().selected_hex(),
|
||||
rc.teams()[rc.screen().viewing_team()],
|
||||
rc.screen().show_everything());
|
||||
}
|
||||
|
||||
static config gray_inactive(reports::context & rc, const std::string &str, const std::string& tooltip = "")
|
||||
{
|
||||
if ( rc.screen().viewing_side() == rc.screen().playing_side() )
|
||||
|
@ -741,7 +748,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res
|
|||
};
|
||||
|
||||
{
|
||||
auto ctx = at.specials_context(unit_const_ptr(&u), hex, u.side() == rc.screen().playing_side());
|
||||
auto ctx = at.specials_context(u.shared_from_this(), hex, u.side() == rc.screen().playing_side());
|
||||
int base_damage = at.damage();
|
||||
int specials_damage = at.modified_damage(false);
|
||||
int damage_multiplier = 100;
|
||||
|
@ -923,7 +930,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res
|
|||
//If we have a second unit, do the 2-unit specials_context
|
||||
bool attacking = (u.side() == rc.screen().playing_side());
|
||||
auto ctx = (sec_u == nullptr) ? at.specials_context_for_listing(attacking) :
|
||||
at.specials_context(unit_const_ptr(&u), unit_const_ptr(sec_u), hex, sec_u->get_location(), attacking, sec_u_weapon);
|
||||
at.specials_context(u.shared_from_this(), sec_u->shared_from_this(), hex, sec_u->get_location(), attacking, sec_u_weapon);
|
||||
|
||||
boost::dynamic_bitset<> active;
|
||||
const std::vector<std::pair<t_string, t_string>> &specials = at.special_tooltips(&active);
|
||||
|
@ -978,12 +985,12 @@ static std::string format_hp(unsigned hp)
|
|||
return res.str();
|
||||
}
|
||||
|
||||
static config unit_weapons(reports::context & rc, const unit *attacker, const map_location &attacker_pos, const unit *defender, bool show_attacker)
|
||||
static config unit_weapons(reports::context & rc, unit_const_ptr attacker, const map_location &attacker_pos, const unit *defender, bool show_attacker)
|
||||
{
|
||||
if (!attacker || !defender) return config();
|
||||
|
||||
const unit* u = show_attacker ? attacker : defender;
|
||||
const unit* sec_u = !show_attacker ? attacker : defender;
|
||||
const unit* u = show_attacker ? attacker.get() : defender;
|
||||
const unit* sec_u = !show_attacker ? attacker.get() : defender;
|
||||
const map_location unit_loc = show_attacker ? attacker_pos : defender->get_location();
|
||||
|
||||
std::ostringstream str, tooltip;
|
||||
|
@ -1140,11 +1147,11 @@ REPORT_GENERATOR(unit_weapons, rc)
|
|||
}
|
||||
REPORT_GENERATOR(highlighted_unit_weapons, rc)
|
||||
{
|
||||
const unit *u = get_selected_unit(rc);
|
||||
unit_const_ptr u = get_selected_unit_ptr(rc);
|
||||
const unit *sec_u = get_visible_unit(rc);
|
||||
|
||||
if (!u) return report_unit_weapons(rc);
|
||||
if (!sec_u || u == sec_u) return unit_weapons(rc, sec_u, rc.screen().mouseover_hex());
|
||||
if (!sec_u || u.get() == sec_u) return unit_weapons(rc, sec_u, rc.screen().mouseover_hex());
|
||||
|
||||
map_location highlighted_hex = rc.screen().displayed_unit_hex();
|
||||
map_location attack_loc;
|
||||
|
@ -1154,15 +1161,16 @@ REPORT_GENERATOR(highlighted_unit_weapons, rc)
|
|||
if (!attack_loc.valid())
|
||||
return unit_weapons(rc, sec_u, rc.screen().mouseover_hex());
|
||||
|
||||
//TODO: shouldn't this pass sec_u as secodn parameter ?
|
||||
return unit_weapons(rc, u, attack_loc, sec_u, false);
|
||||
}
|
||||
REPORT_GENERATOR(selected_unit_weapons, rc)
|
||||
{
|
||||
const unit *u = get_selected_unit(rc);
|
||||
unit_const_ptr u = get_selected_unit_ptr(rc);
|
||||
const unit *sec_u = get_visible_unit(rc);
|
||||
|
||||
if (!u) return config();
|
||||
if (!sec_u || u == sec_u) return unit_weapons(rc, u, u->get_location());
|
||||
if (!sec_u || u.get() == sec_u) return unit_weapons(rc, u.get(), u->get_location());
|
||||
|
||||
map_location highlighted_hex = rc.screen().displayed_unit_hex();
|
||||
map_location attack_loc;
|
||||
|
@ -1170,7 +1178,7 @@ REPORT_GENERATOR(selected_unit_weapons, rc)
|
|||
attack_loc = rc.mhb()->current_unit_attacks_from(highlighted_hex);
|
||||
|
||||
if (!attack_loc.valid())
|
||||
return unit_weapons(rc, u, u->get_location());
|
||||
return unit_weapons(rc, u.get(), u->get_location());
|
||||
|
||||
return unit_weapons(rc, u, attack_loc, sec_u, true);
|
||||
}
|
||||
|
|
|
@ -341,7 +341,8 @@ static int impl_animator_collect(lua_State* L) {
|
|||
static int impl_add_animation(lua_State* L)
|
||||
{
|
||||
unit_animator& anim = *static_cast<unit_animator*>(luaL_checkudata(L, 1, animatorKey));
|
||||
unit& u = luaW_checkunit(L, 2);
|
||||
unit_ptr up = luaW_checkunit_ptr(L, 2, false);
|
||||
unit& u = *up;
|
||||
std::string which = luaL_checkstring(L, 3);
|
||||
|
||||
using hit_type = unit_animation::hit_type;
|
||||
|
@ -435,7 +436,7 @@ static int impl_add_animation(lua_State* L)
|
|||
return luaW_type_error(L, 5, "table of options");
|
||||
}
|
||||
|
||||
anim.add_animation(&u, which, u.get_location(), dest, v1, bars, text, color, hits, primary, secondary, v2);
|
||||
anim.add_animation(up, which, u.get_location(), dest, v1, bars, text, color, hits, primary, secondary, v2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2660,7 +2661,7 @@ int game_lua_kernel::intf_simulate_combat(lua_State *L)
|
|||
}
|
||||
|
||||
battle_context context(units(), att->get_location(),
|
||||
def->get_location(), att_w, def_w, 0.0, nullptr, att.get(), def.get());
|
||||
def->get_location(), att_w, def_w, 0.0, nullptr, att, def);
|
||||
|
||||
luaW_pushsimdata(L, context.get_attacker_combatant());
|
||||
luaW_pushsimdata(L, context.get_defender_combatant());
|
||||
|
@ -3960,7 +3961,7 @@ int game_lua_kernel::intf_teleport(lua_State *L)
|
|||
units().move(src_loc, vacant_dst);
|
||||
unit::clear_status_caches();
|
||||
|
||||
u = &*units().find(vacant_dst);
|
||||
u = units().find(vacant_dst).get_shared_ptr();
|
||||
u->anim_comp().set_standing();
|
||||
|
||||
if ( clear_shroud ) {
|
||||
|
|
|
@ -903,7 +903,7 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon, u
|
|||
: parent(weapon.shared_from_this())
|
||||
{
|
||||
weapon.self_ = self;
|
||||
weapon.other_ = nullptr;
|
||||
weapon.other_ = unit_ptr();
|
||||
weapon.self_loc_ = loc;
|
||||
weapon.other_loc_ = map_location::null_location();
|
||||
weapon.is_attacker_ = attacking;
|
||||
|
@ -922,8 +922,8 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon, c
|
|||
: parent(weapon.shared_from_this())
|
||||
{
|
||||
UNUSED(self_type);
|
||||
weapon.self_ = nullptr;
|
||||
weapon.other_ = nullptr;
|
||||
weapon.self_ = unit_ptr();
|
||||
weapon.other_ = unit_ptr();
|
||||
weapon.self_loc_ = loc;
|
||||
weapon.other_loc_ = map_location::null_location();
|
||||
weapon.is_attacker_ = attacking;
|
||||
|
@ -941,8 +941,8 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon, b
|
|||
attack_type::specials_context_t::~specials_context_t()
|
||||
{
|
||||
if(was_moved) return;
|
||||
parent->self_ = nullptr;
|
||||
parent->other_ = nullptr;
|
||||
parent->self_ = unit_ptr();
|
||||
parent->other_ = unit_ptr();
|
||||
parent->self_loc_ = map_location::null_location();
|
||||
parent->other_loc_ = map_location::null_location();
|
||||
parent->is_attacker_ = false;
|
||||
|
@ -1217,13 +1217,13 @@ bool attack_type::special_active_impl(const_attack_ptr self_attack, const_attack
|
|||
if(self == nullptr) {
|
||||
unit_map::const_iterator it = units.find(self_loc);
|
||||
if(it.valid()) {
|
||||
self = it.get_shared_ptr().get();
|
||||
self = it.get_shared_ptr();
|
||||
}
|
||||
}
|
||||
if(other == nullptr) {
|
||||
unit_map::const_iterator it = units.find(other_loc);
|
||||
if(it.valid()) {
|
||||
other = it.get_shared_ptr().get();
|
||||
other = it.get_shared_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -375,7 +375,7 @@ unit_animation::unit_animation(const config& cfg,const std::string& frame_string
|
|||
}
|
||||
|
||||
int unit_animation::matches(const display& disp, const map_location& loc, const map_location& second_loc,
|
||||
const unit* my_unit, const std::string& event, const int value, hit_type hit, const_attack_ptr attack,
|
||||
unit_const_ptr my_unit, const std::string& event, const int value, hit_type hit, const_attack_ptr attack,
|
||||
const_attack_ptr second_attack, int value2) const
|
||||
{
|
||||
int result = base_score_;
|
||||
|
@ -1291,7 +1291,7 @@ void unit_animation::particle::start_animation(int start_time)
|
|||
last_frame_begin_time_ = get_begin_time() -1;
|
||||
}
|
||||
|
||||
void unit_animator::add_animation(const unit* animated_unit
|
||||
void unit_animator::add_animation(unit_const_ptr animated_unit
|
||||
, const std::string& event
|
||||
, const map_location &src
|
||||
, const map_location &dst
|
||||
|
@ -1309,12 +1309,12 @@ void unit_animator::add_animation(const unit* animated_unit
|
|||
display* disp = display::get_singleton();
|
||||
|
||||
anim_elem tmp;
|
||||
tmp.my_unit = unit_const_ptr(animated_unit);
|
||||
tmp.my_unit = std::move(animated_unit);
|
||||
tmp.text = text;
|
||||
tmp.text_color = text_color;
|
||||
tmp.src = src;
|
||||
tmp.with_bars= with_bars;
|
||||
tmp.animation = animated_unit->anim_comp().choose_animation(*disp, src, event, dst, value, hit_type, attack, second_attack, value2);
|
||||
tmp.animation = tmp.my_unit->anim_comp().choose_animation(*disp, src, event, dst, value, hit_type, attack, second_attack, value2);
|
||||
|
||||
if(!tmp.animation) return;
|
||||
|
||||
|
@ -1322,7 +1322,7 @@ void unit_animator::add_animation(const unit* animated_unit
|
|||
animated_units_.push_back(std::move(tmp));
|
||||
}
|
||||
|
||||
void unit_animator::add_animation(const unit* animated_unit
|
||||
void unit_animator::add_animation(unit_const_ptr animated_unit
|
||||
, const unit_animation* anim
|
||||
, const map_location &src
|
||||
, bool with_bars
|
||||
|
@ -1332,7 +1332,7 @@ void unit_animator::add_animation(const unit* animated_unit
|
|||
if(!animated_unit) return;
|
||||
|
||||
anim_elem tmp;
|
||||
tmp.my_unit = unit_const_ptr(animated_unit);
|
||||
tmp.my_unit = std::move(animated_unit);
|
||||
tmp.text = text;
|
||||
tmp.text_color = text_color;
|
||||
tmp.src = src;
|
||||
|
@ -1345,7 +1345,7 @@ void unit_animator::add_animation(const unit* animated_unit
|
|||
animated_units_.push_back(std::move(tmp));
|
||||
}
|
||||
|
||||
void unit_animator::replace_anim_if_invalid(const unit* animated_unit
|
||||
void unit_animator::replace_anim_if_invalid(unit_const_ptr animated_unit
|
||||
, const std::string& event
|
||||
, const map_location &src
|
||||
, const map_location & dst
|
||||
|
@ -1367,7 +1367,7 @@ void unit_animator::replace_anim_if_invalid(const unit* animated_unit
|
|||
*disp, src, dst, animated_unit, event, value, hit_type, attack, second_attack, value2) > unit_animation::MATCH_FAIL)
|
||||
{
|
||||
anim_elem tmp;
|
||||
tmp.my_unit = unit_const_ptr(animated_unit);
|
||||
tmp.my_unit = animated_unit;
|
||||
tmp.text = text;
|
||||
tmp.text_color = text_color;
|
||||
tmp.src = src;
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
static void fill_initial_animations(std::vector<unit_animation>& animations, const config& cfg);
|
||||
static void add_anims(std::vector<unit_animation>& animations, const config& cfg);
|
||||
|
||||
int matches(const display& disp, const map_location& loc, const map_location& second_loc, const unit* my_unit, const std::string& event = "", const int value = 0, hit_type hit = hit_type::INVALID, const_attack_ptr attack = nullptr, const_attack_ptr second_attack = nullptr, int value2 = 0) const;
|
||||
int matches(const display& disp, const map_location& loc, const map_location& second_loc, unit_const_ptr my_unit, const std::string& event = "", const int value = 0, hit_type hit = hit_type::INVALID, const_attack_ptr attack = nullptr, const_attack_ptr second_attack = nullptr, int value2 = 0) const;
|
||||
|
||||
const unit_frame& get_last_frame() const
|
||||
{
|
||||
|
@ -201,14 +201,14 @@ public:
|
|||
start_time_(INT_MIN)
|
||||
{}
|
||||
|
||||
void add_animation(const unit* animated_unit
|
||||
void add_animation(unit_const_ptr animated_unit
|
||||
, const unit_animation* animation
|
||||
, const map_location& src = map_location::null_location()
|
||||
, bool with_bars = false
|
||||
, const std::string& text = ""
|
||||
, const color_t text_color = {0,0,0});
|
||||
|
||||
void add_animation(const unit* animated_unit
|
||||
void add_animation(unit_const_ptr animated_unit
|
||||
, const std::string& event
|
||||
, const map_location& src = map_location::null_location()
|
||||
, const map_location& dst = map_location::null_location()
|
||||
|
@ -222,7 +222,7 @@ public:
|
|||
, const_attack_ptr second_attack = nullptr
|
||||
, int value2 = 0);
|
||||
|
||||
void replace_anim_if_invalid(const unit* animated_unit
|
||||
void replace_anim_if_invalid(unit_const_ptr animated_unit
|
||||
, const std::string& event
|
||||
, const map_location& src = map_location::null_location()
|
||||
, const map_location& dst = map_location::null_location()
|
||||
|
@ -257,7 +257,7 @@ private:
|
|||
struct anim_elem
|
||||
{
|
||||
anim_elem()
|
||||
: my_unit(0)
|
||||
: my_unit()
|
||||
, animation(0)
|
||||
, text()
|
||||
, text_color()
|
||||
|
|
|
@ -32,7 +32,7 @@ const unit_animation* unit_animation_component::choose_animation(const display&
|
|||
std::vector<const unit_animation*> options;
|
||||
int max_val = unit_animation::MATCH_FAIL;
|
||||
for(const unit_animation& anim : animations_) {
|
||||
int matching = anim.matches(disp,loc,second_loc,&u_,event,value,hit,attack,second_attack,swing_num);
|
||||
int matching = anim.matches(disp,loc,second_loc,u_.shared_from_this(),event,value,hit,attack,second_attack,swing_num);
|
||||
if(matching > unit_animation::MATCH_FAIL && matching == max_val) {
|
||||
options.push_back(&anim);
|
||||
} else if(matching > max_val) {
|
||||
|
|
|
@ -145,7 +145,7 @@ public:
|
|||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef typename iter_types::value_type value_type;
|
||||
typedef boost::intrusive_ptr<value_type> pointer;
|
||||
typedef std::shared_ptr<value_type> pointer;
|
||||
typedef value_type& reference;
|
||||
typedef typename iter_types::container_type container_type;
|
||||
typedef typename iter_types::iterator_type iterator_type;
|
||||
|
@ -388,14 +388,14 @@ public:
|
|||
unit_ptr find_unit_ptr(const T& val)
|
||||
{
|
||||
auto res = find(val);
|
||||
return res != end() ? res.get_shared_ptr() : unit_ptr();
|
||||
return res != end() ? unit_ptr(res.get_shared_ptr()) : unit_ptr();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
unit_const_ptr find_unit_ptr(const T& val) const
|
||||
{
|
||||
auto res = find(val);
|
||||
return res != end() ? res.get_shared_ptr() : unit_ptr();
|
||||
return res != end() ? unit_const_ptr(res.get_shared_ptr()) : unit_const_ptr();
|
||||
}
|
||||
|
||||
unit_iterator find_leader(int side);
|
||||
|
|
|
@ -20,14 +20,13 @@
|
|||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include "utils/shared_reference.hpp"
|
||||
class unit;
|
||||
|
||||
void intrusive_ptr_add_ref(const unit *);
|
||||
void intrusive_ptr_release(const unit *);
|
||||
|
||||
typedef boost::intrusive_ptr<unit> unit_ptr;
|
||||
typedef boost::intrusive_ptr<const unit> unit_const_ptr;
|
||||
typedef utils::shared_reference<unit> nonempty_unit_ptr;
|
||||
typedef utils::shared_reference<const unit> nonempty_unit_const_ptr;
|
||||
typedef std::shared_ptr<unit> unit_ptr;
|
||||
typedef std::shared_ptr<const unit> unit_const_ptr;
|
||||
|
||||
// And attacks too!
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ void teleport_unit_between(const map_location& a, const map_location& b, unit& t
|
|||
else
|
||||
disp.scroll_to_tile(a, game_display::ONSCREEN, true, false);
|
||||
unit_animator animator;
|
||||
animator.add_animation(&temp_unit,"pre_teleport",a);
|
||||
animator.add_animation(temp_unit.shared_from_this(),"pre_teleport",a);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void teleport_unit_between(const map_location& a, const map_location& b, unit& t
|
|||
else
|
||||
disp.scroll_to_tile(b, game_display::ONSCREEN, true, false);
|
||||
unit_animator animator;
|
||||
animator.add_animation(&temp_unit,"post_teleport",b);
|
||||
animator.add_animation(temp_unit.shared_from_this(),"post_teleport",b);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ int move_unit_between(const map_location& a,
|
|||
temp_unit->set_location(a);
|
||||
disp.invalidate(a);
|
||||
temp_unit->set_facing(a.get_relative_dir(b));
|
||||
animator.replace_anim_if_invalid(temp_unit.get(),"movement",a,b,step_num,
|
||||
animator.replace_anim_if_invalid(temp_unit,"movement",a,b,step_num,
|
||||
false,"",{0,0,0},unit_animation::hit_type::INVALID,nullptr,nullptr,step_left);
|
||||
animator.start_animations();
|
||||
animator.pause_animation();
|
||||
|
@ -293,7 +293,7 @@ void unit_mover::start(unit_ptr u)
|
|||
}
|
||||
|
||||
// extra immobile movement animation for take-off
|
||||
animator_.add_animation(temp_unit_ptr_.get(), "pre_movement", path_[0], path_[1]);
|
||||
animator_.add_animation(temp_unit_ptr_.get_unit_ptr(), "pre_movement", path_[0], path_[1]);
|
||||
animator_.start_animations();
|
||||
animator_.wait_for_end();
|
||||
animator_.clear();
|
||||
|
@ -462,7 +462,7 @@ void unit_mover::finish(unit_ptr u, map_location::DIRECTION dir)
|
|||
temp_unit_ptr_->set_facing(final_dir);
|
||||
|
||||
// Animation
|
||||
animator_.add_animation(temp_unit_ptr_.get(), "post_movement", end_loc);
|
||||
animator_.add_animation(temp_unit_ptr_.get_unit_ptr(), "post_movement", end_loc);
|
||||
animator_.start_animations();
|
||||
animator_.wait_for_end();
|
||||
animator_.clear();
|
||||
|
@ -522,7 +522,7 @@ void move_unit(const std::vector<map_location>& path, unit_ptr u,
|
|||
void reset_helpers(const unit *attacker,const unit *defender);
|
||||
|
||||
void unit_draw_weapon(const map_location& loc, unit& attacker,
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& defender_loc,unit* defender)
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& defender_loc, unit_ptr defender)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(do_not_show_anims(disp) || disp->fogged(loc) || !preferences::show_combat()) {
|
||||
|
@ -531,16 +531,18 @@ void unit_draw_weapon(const map_location& loc, unit& attacker,
|
|||
unit_animator animator;
|
||||
attacker.set_facing(loc.get_relative_dir(defender_loc));
|
||||
defender->set_facing(defender_loc.get_relative_dir(loc));
|
||||
animator.add_animation(&attacker,"draw_weapon",loc,defender_loc,0,true,"",{0,0,0},unit_animation::hit_type::HIT,attack,secondary_attack,0);
|
||||
animator.add_animation(defender,"draw_weapon",defender_loc,loc,0,true,"",{0,0,0},unit_animation::hit_type::MISS,secondary_attack,attack,0);
|
||||
animator.add_animation(attacker.shared_from_this(),"draw_weapon",loc,defender_loc,0,true,"",{0,0,0},unit_animation::hit_type::HIT,attack,secondary_attack,0);
|
||||
if(defender) {
|
||||
animator.add_animation(defender,"draw_weapon",defender_loc,loc,0,true,"",{0,0,0},unit_animation::hit_type::MISS,secondary_attack,attack,0);
|
||||
}
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
|
||||
const_attack_ptr primary_attack,const_attack_ptr secondary_attack, const map_location& secondary_loc,unit* secondary_unit)
|
||||
void unit_sheath_weapon(const map_location& primary_loc, unit_ptr primary_unit,
|
||||
const_attack_ptr primary_attack,const_attack_ptr secondary_attack, const map_location& secondary_loc,unit_ptr secondary_unit)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(do_not_show_anims(disp) || disp->fogged(primary_loc) || !preferences::show_combat()) {
|
||||
|
@ -564,13 +566,13 @@ void unit_sheath_weapon(const map_location& primary_loc, unit* primary_unit,
|
|||
if(secondary_unit) {
|
||||
secondary_unit->anim_comp().set_standing();
|
||||
}
|
||||
reset_helpers(primary_unit,secondary_unit);
|
||||
reset_helpers(&*primary_unit,&*secondary_unit);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void unit_die(const map_location& loc, unit& loser,
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& winner_loc,unit* winner)
|
||||
const_attack_ptr attack,const_attack_ptr secondary_attack, const map_location& winner_loc, unit_ptr winner)
|
||||
{
|
||||
display* disp = display::get_singleton();
|
||||
if(do_not_show_anims(disp) || disp->fogged(loc) || !preferences::show_combat()) {
|
||||
|
@ -578,14 +580,16 @@ void unit_die(const map_location& loc, unit& loser,
|
|||
}
|
||||
unit_animator animator;
|
||||
// hide the hp/xp bars of the loser (useless and prevent bars around an erased unit)
|
||||
animator.add_animation(&loser,"death",loc,winner_loc,0,false,"",{0,0,0},unit_animation::hit_type::KILL,attack,secondary_attack,0);
|
||||
animator.add_animation(loser.shared_from_this(),"death",loc,winner_loc,0,false,"",{0,0,0},unit_animation::hit_type::KILL,attack,secondary_attack,0);
|
||||
// but show the bars of the winner (avoid blinking and show its xp gain)
|
||||
animator.add_animation(winner,"victory",winner_loc,loc,0,true,"",{0,0,0},
|
||||
if(winner) {
|
||||
animator.add_animation(winner,"victory",winner_loc,loc,0,true,"",{0,0,0},
|
||||
unit_animation::hit_type::KILL,secondary_attack,attack,0);
|
||||
}
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
|
||||
reset_helpers(winner, &loser);
|
||||
reset_helpers(&*winner, &loser);
|
||||
|
||||
if(events::mouse_handler* mousehandler = events::mouse_handler::get_singleton()) {
|
||||
mousehandler->invalidate_reachmap();
|
||||
|
@ -636,7 +640,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
|
||||
unit_animator animator;
|
||||
|
||||
animator.add_animation(&attacker, "attack", att->get_location(), def->get_location(), damage, true, text_2,
|
||||
animator.add_animation(attacker.shared_from_this(), "attack", att->get_location(), def->get_location(), damage, true, text_2,
|
||||
(drain_amount >= 0) ? color_t(0, 255, 0) : color_t(255, 0, 0), hit_type, attack.shared_from_this(),
|
||||
secondary_attack, swing);
|
||||
|
||||
|
@ -644,7 +648,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
const unit_animation* defender_anim = def->anim_comp().choose_animation(*disp, def->get_location(), "defend",
|
||||
att->get_location(), damage, hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
|
||||
animator.add_animation(&defender, defender_anim, def->get_location(), true, text, {255, 0, 0});
|
||||
animator.add_animation(defender.shared_from_this(), defender_anim, def->get_location(), true, text, {255, 0, 0});
|
||||
|
||||
for(const unit_ability& ability : attacker.get_abilities_weapons("leadership", attack.shared_from_this(), secondary_attack)) {
|
||||
if(ability.teacher_loc == a) {
|
||||
|
@ -658,7 +662,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
unit_map::const_iterator leader = board.units().find(ability.teacher_loc);
|
||||
assert(leader.valid());
|
||||
leader->set_facing(ability.teacher_loc.get_relative_dir(a));
|
||||
animator.add_animation(&*leader, "leading", ability.teacher_loc,
|
||||
animator.add_animation(leader.get_shared_ptr(), "leading", ability.teacher_loc,
|
||||
att->get_location(), damage, true, "", {0,0,0},
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
}
|
||||
|
@ -675,7 +679,7 @@ void unit_attack(display * disp, game_board & board,
|
|||
unit_map::const_iterator helper = board.units().find(ability.teacher_loc);
|
||||
assert(helper.valid());
|
||||
helper->set_facing(ability.teacher_loc.get_relative_dir(b));
|
||||
animator.add_animation(&*helper, "resistance", ability.teacher_loc,
|
||||
animator.add_animation(helper.get_shared_ptr(), "resistance", ability.teacher_loc,
|
||||
def->get_location(), damage, true, "", {0,0,0},
|
||||
hit_type, attack.shared_from_this(), secondary_attack, swing);
|
||||
}
|
||||
|
@ -765,13 +769,13 @@ void unit_recruited(const map_location& loc,const map_location& leader_loc)
|
|||
if (leader != disp->get_units().end()) {
|
||||
leader->set_facing(leader_loc.get_relative_dir(loc));
|
||||
if (leader_visible) {
|
||||
animator.add_animation(&*leader, "recruiting", leader_loc, loc, 0, true);
|
||||
animator.add_animation(leader.get_shared_ptr(), "recruiting", leader_loc, loc, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
disp->draw();
|
||||
}
|
||||
animator.add_animation(&*u, "recruited", loc, leader_loc);
|
||||
animator.add_animation(u.get_shared_ptr(), "recruited", loc, leader_loc);
|
||||
animator.start_animations();
|
||||
animator.wait_for_end();
|
||||
animator.set_all_standing();
|
||||
|
@ -798,22 +802,22 @@ void unit_healing(unit &healed, const std::vector<unit *> &healers, int healing,
|
|||
|
||||
for (unit *h : healers) {
|
||||
h->set_facing(h->get_location().get_relative_dir(healed_loc));
|
||||
animator.add_animation(h, "healing", h->get_location(),
|
||||
animator.add_animation(h->shared_from_this(), "healing", h->get_location(),
|
||||
healed_loc, healing);
|
||||
}
|
||||
|
||||
if (healing < 0) {
|
||||
animator.add_animation(&healed, "poisoned", healed_loc,
|
||||
animator.add_animation(healed.shared_from_this(), "poisoned", healed_loc,
|
||||
map_location::null_location(), -healing, false,
|
||||
number_and_text(-healing, extra_text),
|
||||
{255,0,0});
|
||||
} else if ( healing > 0 ) {
|
||||
animator.add_animation(&healed, "healed", healed_loc,
|
||||
animator.add_animation(healed.shared_from_this(), "healed", healed_loc,
|
||||
map_location::null_location(), healing, false,
|
||||
number_and_text(healing, extra_text),
|
||||
{0,255,0});
|
||||
} else {
|
||||
animator.add_animation(&healed, "healed", healed_loc,
|
||||
animator.add_animation(healed.shared_from_this(), "healed", healed_loc,
|
||||
map_location::null_location(), 0, false,
|
||||
extra_text, {0,255,0});
|
||||
}
|
||||
|
|
|
@ -86,13 +86,13 @@ void move_unit(const std::vector<map_location>& path, unit_ptr u,
|
|||
* Play a pre-fight animation
|
||||
* First unit is the attacker, second unit the defender
|
||||
*/
|
||||
void unit_draw_weapon( const map_location& loc, unit& u, const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
void unit_draw_weapon( const map_location& loc, unit& u, const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit_ptr defender=unit_ptr());
|
||||
|
||||
/**
|
||||
* Play a post-fight animation
|
||||
* Both unit can be set to null, only valid units will play their animation
|
||||
*/
|
||||
void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit * defender=nullptr);
|
||||
void unit_sheath_weapon( const map_location& loc, unit_ptr u=unit_ptr(), const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,const map_location& defender_loc = map_location::null_location(), unit_ptr defender=unit_ptr());
|
||||
|
||||
/**
|
||||
* Show a unit fading out.
|
||||
|
@ -102,7 +102,7 @@ void unit_sheath_weapon( const map_location& loc, unit* u=nullptr, const_attack_
|
|||
void unit_die( const map_location& loc, unit& u,
|
||||
const_attack_ptr attack=nullptr, const_attack_ptr secondary_attack=nullptr,
|
||||
const map_location& winner_loc=map_location::null_location(),
|
||||
unit* winner=nullptr);
|
||||
unit_ptr winner = unit_ptr());
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -208,37 +208,6 @@ namespace
|
|||
}
|
||||
} // end anon namespace
|
||||
|
||||
/**
|
||||
* Intrusive Pointer interface
|
||||
*
|
||||
**/
|
||||
|
||||
void intrusive_ptr_add_ref(const unit* u)
|
||||
{
|
||||
assert(u->ref_count_ >= 0);
|
||||
// the next code line is to notice possible wrongly initialized units.
|
||||
// The 100000 is picked rather randomly. If you are in the situation
|
||||
// that you can actually have more then 100000 intrusive_ptr to one unit
|
||||
// or if you are sure that the refcounting system works
|
||||
// then feel free to remove the next line
|
||||
assert(u->ref_count_ < 100000);
|
||||
if(u->ref_count_ == 0) {
|
||||
LOG_UT << "Freshly constructed" << std::endl;
|
||||
}
|
||||
++(u->ref_count_);
|
||||
}
|
||||
|
||||
void intrusive_ptr_release(const unit* u)
|
||||
{
|
||||
assert(u->ref_count_ >= 1);
|
||||
assert(u->ref_count_ < 100000); //See comment in intrusive_ptr_add_ref
|
||||
if(--(u->ref_count_) == 0)
|
||||
{
|
||||
DBG_UT << "Deleting a unit: id = " << u->id() << ", uid = " << u->underlying_id() << std::endl;
|
||||
delete u;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string ID to a unit_type.
|
||||
* Throws a game_error exception if the string does not correspond to a type.
|
||||
|
@ -297,7 +266,7 @@ struct ptr_vector_pushback
|
|||
|
||||
// Copy constructor
|
||||
unit::unit(const unit& o)
|
||||
: ref_count_(0)
|
||||
: std::enable_shared_from_this<unit>()
|
||||
, loc_(o.loc_)
|
||||
, advances_to_(o.advances_to_)
|
||||
, type_(o.type_)
|
||||
|
@ -377,8 +346,8 @@ unit::unit(const unit& o)
|
|||
}
|
||||
}
|
||||
|
||||
unit::unit()
|
||||
: ref_count_(0)
|
||||
unit::unit(unit_ctor_t)
|
||||
: std::enable_shared_from_this<unit>()
|
||||
, loc_()
|
||||
, advances_to_()
|
||||
, type_(nullptr)
|
||||
|
|
|
@ -126,7 +126,7 @@ private:
|
|||
/**
|
||||
* This class represents a *single* unit of a specific type.
|
||||
*/
|
||||
class unit
|
||||
class unit : public std::enable_shared_from_this<unit>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
@ -145,7 +145,13 @@ private:
|
|||
// Copy constructor
|
||||
unit(const unit& u);
|
||||
|
||||
unit();
|
||||
|
||||
struct unit_ctor_t {};
|
||||
public:
|
||||
//private default ctor, butusing constructor to allow calling make_shared<unit> in create().
|
||||
unit(unit_ctor_t);
|
||||
unit() = delete;
|
||||
private:
|
||||
enum UNIT_ATTRIBUTE
|
||||
{
|
||||
UA_MAX_HP,
|
||||
|
@ -184,7 +190,7 @@ public:
|
|||
/** Initializes a unit from a config */
|
||||
static unit_ptr create(const config& cfg, bool use_traits = false, const vconfig* vcfg = nullptr)
|
||||
{
|
||||
unit_ptr res(new unit());
|
||||
unit_ptr res = std::make_shared<unit>(unit_ctor_t());
|
||||
res->init(cfg, use_traits, vcfg);
|
||||
return res;
|
||||
}
|
||||
|
@ -196,20 +202,21 @@ public:
|
|||
*/
|
||||
static unit_ptr create(const unit_type& t, int side, bool real_unit, unit_race::GENDER gender = unit_race::NUM_GENDERS, const std::string& variation = "")
|
||||
{
|
||||
unit_ptr res(new unit());
|
||||
unit_ptr res = std::make_shared<unit>(unit_ctor_t());
|
||||
res->init(t, side, real_unit, gender, variation);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
unit_ptr clone() const
|
||||
{
|
||||
return unit_ptr(new unit(*this));
|
||||
return unit_ptr(std::shared_ptr<unit>(new unit(*this)));
|
||||
}
|
||||
|
||||
unit_ptr shared_from_this()
|
||||
{
|
||||
return unit_ptr(this);
|
||||
}
|
||||
//unit_ptr shared_from_this()
|
||||
//{
|
||||
// return unit_ptr(this);
|
||||
//}
|
||||
|
||||
virtual ~unit();
|
||||
|
||||
|
@ -1772,21 +1779,11 @@ public:
|
|||
*/
|
||||
unit& mark_clone(bool is_temporary);
|
||||
|
||||
/** @} */
|
||||
|
||||
long ref_count() const
|
||||
{
|
||||
return ref_count_;
|
||||
}
|
||||
|
||||
friend void intrusive_ptr_add_ref(const unit*);
|
||||
friend void intrusive_ptr_release(const unit*);
|
||||
|
||||
void set_appearance_changed(bool value) { appearance_changed_ = value; }
|
||||
bool appearance_changed() const { return appearance_changed_; }
|
||||
|
||||
protected:
|
||||
mutable long ref_count_; // used by intrusive_ptr
|
||||
|
||||
private:
|
||||
map_location loc_;
|
||||
|
|
90
src/utils/shared_reference.hpp
Normal file
90
src/utils/shared_reference.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (C) 2020 the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace utils {
|
||||
|
||||
template <typename T>
|
||||
class shared_reference
|
||||
{
|
||||
std::shared_ptr<T> m_ptr;
|
||||
|
||||
public:
|
||||
template<typename Y>
|
||||
shared_reference(const shared_reference<Y>& p)
|
||||
: m_ptr(p.m_ptr)
|
||||
{ }
|
||||
template<typename Y>
|
||||
shared_reference(shared_reference<Y>&& p)
|
||||
: m_ptr(std::move(p.m_ptr))
|
||||
{ }
|
||||
template<typename Y>
|
||||
explicit shared_reference(const std::shared_ptr<Y>& p)
|
||||
: m_ptr(p)
|
||||
{
|
||||
if(!p) {
|
||||
throw std::invalid_argument("invalid shared_reference");
|
||||
}
|
||||
}
|
||||
template<typename Y>
|
||||
explicit shared_reference(std::shared_ptr<Y>&& p)
|
||||
: m_ptr(p)
|
||||
{
|
||||
if(!p) {
|
||||
throw std::invalid_argument("invalid shared_reference");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
shared_reference& operator=(shared_reference<Y>&& p)
|
||||
{
|
||||
m_ptr = std::move(p.m_ptr);
|
||||
return *this;
|
||||
}
|
||||
template<typename Y>
|
||||
shared_reference& operator=(const shared_reference<Y>& p)
|
||||
{
|
||||
m_ptr = p.m_ptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~shared_reference() = default;
|
||||
|
||||
operator std::shared_ptr<T>()
|
||||
{ return m_ptr; }
|
||||
|
||||
T* operator->() { return m_ptr.get(); }
|
||||
const T* operator->() const { return m_ptr.get(); }
|
||||
|
||||
T& operator*() { return *m_ptr.get(); }
|
||||
const T& operator*() const { return *m_ptr.get(); }
|
||||
|
||||
template <typename XT, typename...XTypes>
|
||||
friend shared_reference<XT> make_shared_reference(XTypes&&...args);
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename...Types>
|
||||
shared_reference<T> make_shared_reference(Types&&...args)
|
||||
{
|
||||
return shared_reference<T>(std::make_shared<T>(std::forward<Types>(args)...));
|
||||
}
|
||||
|
||||
|
||||
} // namespace utils
|
Loading…
Add table
Reference in a new issue