this changes it so that the during events the attack_type references its
context units always by location, like it was done in 1.12, considering
the soon 1.14 release i think this is the best fix

The problem with the old implementation basically was that if a wml
script replaced the unit in a attack events  the
attack_type::self_/other_ would point to an outdated unit during the
next handler of the same event.
This commit is contained in:
gfgtdf 2018-03-10 19:09:14 +01:00 committed by Celtic Minstrel
parent 7ed2e57ebc
commit b2cb4be47d
5 changed files with 30 additions and 30 deletions

View file

@ -122,11 +122,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(&u, &opp, 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(&opp, &u, opp_loc, u_loc, !attacking, weapon));
}
slows = weapon->get_special_bool("slow");
@ -932,18 +932,18 @@ void attack::fire_event(const std::string& n)
if(a_stats_->weapon != nullptr && a_.valid()) {
if(d_stats_->weapon != nullptr && d_.valid()) {
a_ctx.emplace(a_stats_->weapon->specials_context(a_.get_unit(), d_.get_unit(), a_.loc_, d_.loc_, true, d_stats_->weapon));
a_ctx.emplace(a_stats_->weapon->specials_context(nullptr, nullptr, a_.loc_, d_.loc_, true, d_stats_->weapon));
} else {
a_ctx.emplace(a_stats_->weapon->specials_context(a_.get_unit(), a_.loc_, true));
a_ctx.emplace(a_stats_->weapon->specials_context(nullptr, a_.loc_, true));
}
a_stats_->weapon->write(a_weapon_cfg);
}
if(d_stats_->weapon != nullptr && d_.valid()) {
if(a_stats_->weapon != nullptr && a_.valid()) {
d_ctx.emplace(d_stats_->weapon->specials_context(d_.get_unit(), a_.get_unit(), d_.loc_, a_.loc_, false, a_stats_->weapon));
d_ctx.emplace(d_stats_->weapon->specials_context(nullptr, nullptr, d_.loc_, a_.loc_, false, a_stats_->weapon));
} else {
d_ctx.emplace(d_stats_->weapon->specials_context(d_.get_unit(), d_.loc_, false));
d_ctx.emplace(d_stats_->weapon->specials_context(nullptr, d_.loc_, false));
}
d_stats_->weapon->write(d_weapon_cfg);
}

View file

@ -127,7 +127,7 @@ 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;
auto ctx = weapon->specials_context(attacker.unit_, defender.unit_, attacker.unit_.get_location(), defender.unit_.get_location(), attacker.stats_.is_attacker, defender.stats_.weapon);
auto ctx = weapon->specials_context(&attacker.unit_, &defender.unit_, attacker.unit_.get_location(), defender.unit_.get_location(), attacker.stats_.is_attacker, defender.stats_.weapon);
// Get damage modifiers.
unit_ability_list dmg_specials = weapon->get_specials("damage");

View file

@ -660,7 +660,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res
int damage = 0;
{
auto ctx = at.specials_context(u, displayed_unit_hex, u.side() == rc.screen().playing_side());
auto ctx = at.specials_context(&u, displayed_unit_hex, u.side() == rc.screen().playing_side());
int base_damage = at.damage();
int specials_damage = at.modified_damage(false);
int damage_multiplier = 100;

View file

@ -705,15 +705,15 @@ std::string attack_type::weapon_specials(bool only_active, bool is_backstab) con
*/
attack_type::specials_context_t::specials_context_t(const attack_type& weapon,
const_attack_ptr other_attack,
const unit& self,
const unit& other,
const unit* self,
const unit* other,
const map_location& unit_loc,
const map_location& other_loc,
bool attacking)
: parent(weapon)
: parent(weapon.shared_from_this())
{
weapon.self_ = &self;
weapon.other_ = &other;
weapon.self_ = self;
weapon.other_ = other;
weapon.self_loc_ = unit_loc;
weapon.other_loc_ = other_loc;
weapon.is_attacker_ = attacking;
@ -728,10 +728,10 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon,
* @param[in] loc The location of the unit with this weapon.
* @param[in] attacking Whether or not the unit with this weapon is the attacker.
*/
attack_type::specials_context_t::specials_context_t(const attack_type& weapon, const unit& self, const map_location& loc, bool attacking)
: parent(weapon)
attack_type::specials_context_t::specials_context_t(const attack_type& weapon, const unit* self, const map_location& loc, bool attacking)
: parent(weapon.shared_from_this())
{
weapon.self_ = &self;
weapon.self_ = self;
weapon.other_ = nullptr;
weapon.self_loc_ = loc;
weapon.other_loc_ = map_location::null_location();
@ -748,7 +748,7 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon, c
* @param[in] attacking Whether or not the unit with this weapon is the attacker.
*/
attack_type::specials_context_t::specials_context_t(const attack_type& weapon, const unit_type& self_type, const map_location& loc, bool attacking)
: parent(weapon)
: parent(weapon.shared_from_this())
{
UNUSED(self_type);
weapon.self_ = nullptr;
@ -761,7 +761,7 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon, c
}
attack_type::specials_context_t::specials_context_t(const attack_type& weapon)
: parent(weapon)
: parent(weapon.shared_from_this())
{
weapon.is_for_listing_ = true;
}
@ -769,13 +769,13 @@ attack_type::specials_context_t::specials_context_t(const attack_type& weapon)
attack_type::specials_context_t::~specials_context_t()
{
if(was_moved) return;
parent.self_ = nullptr;
parent.other_ = nullptr;
parent.self_loc_ = map_location::null_location();
parent.other_loc_ = map_location::null_location();
parent.is_attacker_ = false;
parent.other_attack_ = nullptr;
parent.is_for_listing_ = false;
parent->self_ = nullptr;
parent->other_ = nullptr;
parent->self_loc_ = map_location::null_location();
parent->other_loc_ = map_location::null_location();
parent->is_attacker_ = false;
parent->other_attack_ = nullptr;
parent->is_for_listing_ = false;
}
attack_type::specials_context_t::specials_context_t(attack_type::specials_context_t&& other)

View file

@ -111,19 +111,19 @@ private:
mutable bool is_for_listing_ = false;
public:
class specials_context_t {
std::shared_ptr<const attack_type> parent;
friend class attack_type;
const attack_type& parent;
/// Initialize weapon specials context for listing
explicit specials_context_t(const attack_type& weapon);
/// Initialize weapon specials context for a unit type
specials_context_t(const attack_type& weapon, const unit_type& self_type, const map_location& loc, bool attacking = true);
/// Initialize weapon specials context for a single unit
specials_context_t(const attack_type& weapon, const_attack_ptr other_weapon,
const unit& self, const unit& other,
const unit* self, const unit* other,
const map_location& self_loc, const map_location& other_loc,
bool attacking);
/// Initialize weapon specials context for a pair of units
specials_context_t(const attack_type& weapon, const unit& self, const map_location& loc, bool attacking);
specials_context_t(const attack_type& weapon, const unit* self, const map_location& loc, bool attacking);
specials_context_t(const specials_context_t&) = delete;
bool was_moved = false;
public:
@ -133,12 +133,12 @@ public:
};
// Set up a specials context.
// Usage: auto ctx = weapon.specials_context(...);
specials_context_t specials_context(const unit& self, const unit& other,
specials_context_t specials_context(const unit* self, const unit* other,
const map_location& unit_loc, const map_location& other_loc,
bool attacking, const_attack_ptr other_attack) const {
return specials_context_t(*this, other_attack, self, other, unit_loc, other_loc, attacking);
}
specials_context_t specials_context(const unit& self, const map_location& loc, bool attacking = true) const {
specials_context_t specials_context(const unit* self, const map_location& loc, bool attacking = true) const {
return specials_context_t(*this, self, loc, attacking);
}
specials_context_t specials_context(const unit_type& self_type, const map_location& loc, bool attacking = true) const {