Allow abilities.cpp to access units and teams earlier during play_controller::init

Partially reverts 6a21fdc675
Fixes #5643
Fixes #7238

There's a bunch of global things that can be accessed either via global
pointers in the `resource` namespace, or via `display::get_singleton()`. The
singleton and these global pointers are set up in `play_controller::init`,
however there's a section where things are available via the global pointers
but the `display` singleton doesn't exist yet. During that time, checking
whether an ability is active can crash the game.

Removing the global pointers is a good goal, but detouring through a GUI class
to access the data causes its own problems.

The "has already been confirmed valid by both callers" comment is replaced with
an assert, because there's currently at least three callers.
This commit is contained in:
Steve Cotton 2022-12-30 17:42:17 +01:00 committed by Steve Cotton
parent 9d48e0331a
commit 7ddf691e13
2 changed files with 19 additions and 17 deletions

View file

@ -0,0 +1,2 @@
### Miscellaneous and Bug Fixes
* Fixed a crash when checking if abilities are active during game initialisation after loading a saved game. (issues #5643, #7238)

View file

@ -18,10 +18,10 @@
* 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"
#include "game_version.hpp" // for version_info
#include "gettext.hpp"
#include "global.hpp"
#include "lexical_cast.hpp"
@ -134,8 +134,8 @@ namespace {
bool affects_side(const config& cfg, std::size_t side, std::size_t other_side)
{
// display::get_singleton() has already been confirmed valid by both callers.
const team& side_team = display::get_singleton()->get_disp_context().get_team(side);
assert(resources::gameboard);
const team& side_team = resources::gameboard->get_team(side);
if(side == other_side)
return cfg["affect_allies"].to_bool(true);
@ -157,8 +157,8 @@ bool unit::get_ability_bool(const std::string& tag_name, const map_location& loc
}
}
assert(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
const auto adjacent = get_adjacent_tiles(loc);
for(unsigned i = 0; i < adjacent.size(); ++i) {
@ -198,8 +198,8 @@ unit_ability_list unit::get_abilities(const std::string& tag_name, const map_loc
}
}
assert(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
const auto adjacent = get_adjacent_tiles(loc);
for(unsigned i = 0; i < adjacent.size(); ++i) {
@ -358,8 +358,8 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
const auto adjacent = get_adjacent_tiles(loc);
assert(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
for (const config &i : cfg.child_range("filter_adjacent"))
{
@ -517,8 +517,8 @@ 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(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
auto u_itor = units.find(ability_info.teacher_loc);
@ -967,8 +967,8 @@ void attack_type::weapon_specials_impl_adj(
const std::string& affect_adjacents,
bool leader_bool)
{
assert(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
if(self){
const auto adjacent = get_adjacent_tiles(self_loc);
for(unsigned i = 0; i < adjacent.size(); ++i) {
@ -1405,8 +1405,8 @@ 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(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
if(self_){
std::vector<special_match> special_tag_matches_self;
std::vector<special_match> special_id_matches_self;
@ -1561,8 +1561,8 @@ bool attack_type::special_active_impl(
}
// Get the units involved.
assert(display::get_singleton());
const unit_map& units = display::get_singleton()->get_units();
assert(resources::gameboard);
const unit_map& units = resources::gameboard->units();
unit_const_ptr self = self_attack ? self_attack->self_ : other_attack->other_;
unit_const_ptr other = self_attack ? self_attack->other_ : other_attack->self_;