Fix #2615
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:
parent
7ed2e57ebc
commit
b2cb4be47d
5 changed files with 30 additions and 30 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue