Fix crash in scenario editor when placing units
The previous bugfix fixed a crash when loading savegames with units whose
abilities accessed the map while the display_context was still being
constructed, however it reintroduced a bug in the scenario editor. Using the
unit tool always crashed when adding any unit.
This commit uses 4d1fc268b1's code path whenever possible, however it falls
back to 6a21fdc675's code path when 4d1fc268b1
would assert. In practise one
path is used in game and the other is used in the scenario editor, but doing
the logic in this way ensures that any edge cases are going to affect the
scenario editor rather than the game itself.
This commit is contained in:
parent
3892b947af
commit
1485cfd625
2 changed files with 43 additions and 16 deletions
2
changelog_entries/editor_ability_assert.md
Normal file
2
changelog_entries/editor_ability_assert.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
### Editor
|
||||
* Fixed: the unit tool crashes when placing a unit (issue #7296).
|
|
@ -18,6 +18,7 @@
|
|||
* Manage unit-abilities, like heal, cure, and weapon_specials.
|
||||
*/
|
||||
|
||||
#include "display.hpp"
|
||||
#include "display_context.hpp"
|
||||
#include "font/text_formatting.hpp"
|
||||
#include "game_board.hpp"
|
||||
|
@ -131,10 +132,41 @@ A poisoned unit cannot be cured of its poison by a healer, and must seek the car
|
|||
|
||||
namespace {
|
||||
|
||||
const unit_map& get_unit_map()
|
||||
{
|
||||
// Used if we're in the game, including during the construction of the display_context
|
||||
if(resources::gameboard) {
|
||||
return resources::gameboard->units();
|
||||
}
|
||||
|
||||
// If we get here, we're in the scenario editor
|
||||
assert(display::get_singleton());
|
||||
return display::get_singleton()->get_units();
|
||||
}
|
||||
|
||||
const team& get_team(std::size_t side)
|
||||
{
|
||||
// Used if we're in the game, including during the construction of the display_context
|
||||
if(resources::gameboard) {
|
||||
return resources::gameboard->get_team(side);
|
||||
}
|
||||
|
||||
// If we get here, we're in the scenario editor
|
||||
assert(display::get_singleton());
|
||||
return display::get_singleton()->get_disp_context().get_team(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common code for the question "some other unit has an ability, can that ability affect this
|
||||
* unit" - it's not the full answer to that question, just a part of it.
|
||||
*
|
||||
* Although this is called while checking which units' "hides" abilities are active, that's only
|
||||
* for the question "is this unit next to an ally that has a 'camoflages adjacent allies' ability";
|
||||
* not the question "is this unit next to an enemy, therefore visible".
|
||||
*/
|
||||
bool affects_side(const config& cfg, std::size_t side, std::size_t other_side)
|
||||
{
|
||||
assert(resources::gameboard);
|
||||
const team& side_team = resources::gameboard->get_team(side);
|
||||
const team& side_team = get_team(side);
|
||||
|
||||
if(side == other_side)
|
||||
return cfg["affect_allies"].to_bool(true);
|
||||
|
@ -156,8 +188,7 @@ bool unit::get_ability_bool(const std::string& tag_name, const map_location& loc
|
|||
}
|
||||
}
|
||||
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
const auto adjacent = get_adjacent_tiles(loc);
|
||||
for(unsigned i = 0; i < adjacent.size(); ++i) {
|
||||
|
@ -197,8 +228,7 @@ unit_ability_list unit::get_abilities(const std::string& tag_name, const map_loc
|
|||
}
|
||||
}
|
||||
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
const auto adjacent = get_adjacent_tiles(loc);
|
||||
for(unsigned i = 0; i < adjacent.size(); ++i) {
|
||||
|
@ -361,8 +391,7 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
|
|||
|
||||
const auto adjacent = get_adjacent_tiles(loc);
|
||||
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
for (const config &i : cfg.child_range("filter_adjacent"))
|
||||
{
|
||||
|
@ -520,8 +549,7 @@ T get_single_ability_value(const config::attribute_value& v, T def, const unit_a
|
|||
return v.apply_visitor(get_ability_value_visitor(def, [&](const std::string& s) {
|
||||
|
||||
try {
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
auto u_itor = units.find(ability_info.teacher_loc);
|
||||
|
||||
|
@ -881,8 +909,7 @@ std::string attack_type::weapon_specials(bool is_backstab) const
|
|||
}
|
||||
std::string weapon_abilities;
|
||||
std::set<std::string> checking_name;
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
if(self_){
|
||||
for (const config::any_child &sp : self_->abilities().all_children_range()){
|
||||
const bool active = check_self_abilities_impl(shared_from_this(), other_attack_, sp.cfg, self_, self_loc_, AFFECT_SELF, sp.key);
|
||||
|
@ -1373,8 +1400,7 @@ bool attack_type::check_adj_abilities_impl(const_attack_ptr self_attack, const_a
|
|||
*/
|
||||
bool attack_type::has_weapon_ability(const std::string& special, bool special_id, bool special_tags) const
|
||||
{
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
if(self_){
|
||||
std::vector<special_match> special_tag_matches_self;
|
||||
std::vector<special_match> special_id_matches_self;
|
||||
|
@ -1531,8 +1557,7 @@ bool attack_type::special_active_impl(const_attack_ptr self_attack, const_attack
|
|||
}
|
||||
|
||||
// Get the units involved.
|
||||
assert(resources::gameboard);
|
||||
const unit_map& units = resources::gameboard->units();
|
||||
const unit_map& units = get_unit_map();
|
||||
|
||||
unit_const_ptr self = self_attack ? self_attack->self_ : other_attack->other_;
|
||||
unit_const_ptr other = self_attack ? self_attack->other_ : other_attack->self_;
|
||||
|
|
Loading…
Add table
Reference in a new issue