Fix crash on placing a unit with the scenario editor

The unit::get_ability_bool() function accessed resources::gameboard that
is not set in the editor. Now the function receives the display context
as a parameter instead.

I also fixed two crashes on editor startup in MSVC debug builds (both
caused by indexing the teams vector when there aren't any teams), and the
GUI2 unit list dialog showing wrong status icons.
This commit is contained in:
Jyrki Vesterinen 2016-08-27 23:55:59 +03:00
parent 206096cc1e
commit 7573678201
31 changed files with 80 additions and 68 deletions

View file

@ -86,7 +86,7 @@ const std::set<std::string> get_recruits(int side, const map_location &recruit_l
local_result.insert(find_it->recruits().begin(),
find_it->recruits().end());
}
else if ( find_it->is_visible_to_team(current_team, resources::gameboard->map(), false) )
else if ( find_it->is_visible_to_team(current_team, resources::gameboard->map(), *resources::gameboard, false) )
{
// This hex is visibly occupied, so we cannot recruit here.
allow_local = false;
@ -187,7 +187,7 @@ std::vector<unit_const_ptr > get_recalls(int side, const map_location &recall_lo
add_leader_filtered_recalls(find_it.get_shared_ptr(), result);
return result;
}
else if ( find_it->is_visible_to_team(resources::gameboard->teams()[side-1], resources::gameboard->map(), false) )
else if ( find_it->is_visible_to_team(resources::gameboard->teams()[side-1], resources::gameboard->map(), *resources::gameboard, false) )
{
// This hex is visibly occupied, so we cannot recall here.
allow_local = false;
@ -588,7 +588,7 @@ namespace { // Helpers for place_recruit()
for ( unit_itor = units.begin(); unit_itor != units.end(); ++unit_itor ) {
if (resources::gameboard->teams()[unit_itor->side()-1].is_enemy(new_unit.side()) &&
unit_itor->is_visible_to_team(resources::gameboard->teams()[new_unit.side()-1], *map, false)) {
unit_itor->is_visible_to_team(resources::gameboard->teams()[new_unit.side()-1], *map, *resources::gameboard, false)) {
int dist = distance_between(unit_itor->get_location(),recruit_loc) - unit_itor->level();
if (dist < min_dist) {
min_dist = dist;

View file

@ -351,7 +351,7 @@ void calculate_healing(int side, bool update_display)
const team & viewing_team =
resources::gameboard->teams()[resources::screen->viewing_team()];
if (!resources::controller->is_skipping_replay() && update_display &&
patient.is_visible_to_team(viewing_team, resources::gameboard->map(), false) )
patient.is_visible_to_team(viewing_team, resources::gameboard->map(), *resources::gameboard, false) )
{
unit_list.push_front(heal_unit(patient, healers, healing, curing == POISON_CURE));
}

View file

@ -427,7 +427,7 @@ namespace { // Private helpers for move_unit()
if ( neighbor_it != units.end() &&
current_team_->is_enemy(neighbor_it->side()) &&
neighbor_it->invisible(adjacent[i]) )
neighbor_it->invisible(adjacent[i], *resources::gameboard) )
{
// Ambushed!
ambushed_ = true;
@ -735,7 +735,7 @@ namespace { // Private helpers for move_unit()
if ( start != begin_ ) {
// Check for being unable to leave the current hex.
if ( !move_it_->get_ability_bool("skirmisher", *start) &&
if ( !move_it_->get_ability_bool("skirmisher", *start, *resources::gameboard) &&
pathfind::enemy_zoc(*current_team_, *start, *current_team_) )
zoc_stop_ = *start;
}
@ -758,7 +758,7 @@ namespace { // Private helpers for move_unit()
moves_left_.push_back(remaining_moves);
// Check for being unable to leave this hex.
if ( !move_it_->get_ability_bool("skirmisher", *end) &&
if ( !move_it_->get_ability_bool("skirmisher", *end, *resources::gameboard) &&
pathfind::enemy_zoc(*current_team_, *end, *current_team_) )
zoc_stop_ = *end;
}

View file

@ -600,7 +600,7 @@ std::vector<int> get_sides_not_seeing(const unit & target)
size_t team_size = teams.size();
for ( size_t i = 0; i != team_size; ++i)
if ( !target.is_visible_to_team(teams[i], resources::gameboard->map(), false) )
if ( !target.is_visible_to_team(teams[i], resources::gameboard->map(), *resources::gameboard, false) )
// not_see contains side numbers; i is a team index, so add 1.
not_seeing.push_back(i+1);
@ -646,7 +646,7 @@ bool actor_sighted(const unit & target, const std::vector<int> * cache)
needs_event[target.side()-1] = false;
// Exclude those teams that cannot see the target.
for ( size_t i = 0; i != teams_size; ++i )
needs_event[i] = needs_event[i] && target.is_visible_to_team(teams[i], resources::gameboard->map(), false);
needs_event[i] = needs_event[i] && target.is_visible_to_team(teams[i], resources::gameboard->map(), *resources::gameboard, false);
// Cache "jamming".
std::vector< std::map<map_location, int> > jamming_cache(teams_size);

View file

@ -302,7 +302,7 @@ void protect_goal::add_targets(std::back_insert_iterator< std::vector< target >
{
int distance = distance_between(u.get_location(), loc);
if (current_team().is_enemy(u.side()) && distance < radius_ &&
!u.invisible(u.get_location()))
!u.invisible(u.get_location(), *resources::gameboard))
{
DBG_AI_GOAL << "side " << get_side() << ": in " << goal_type << ": found threat target. " << u.get_location() << " is a threat to "<< loc << '\n';
*target_list = target(u.get_location(),

View file

@ -379,7 +379,7 @@ void readonly_context_impl::calculate_moves(const unit_map& units, std::map<map_
}
// We can't see where invisible enemy units might move.
if (enemy && un_it->invisible(un_it->get_location()) && !see_all) {
if (enemy && un_it->invisible(un_it->get_location(), *resources::gameboard) && !see_all) {
continue;
}
// If it's an enemy unit, reset its moves while we do the calculations.

View file

@ -104,7 +104,7 @@ std::shared_ptr<attacks_vector> aspect_attacks_base::analyze_targets() const
// Attack anyone who is on the enemy side,
// and who is not invisible or petrified.
if (current_team().is_enemy(j->side()) && !j->incapacitated() &&
!j->invisible(j->get_location()))
!j->invisible(j->get_location(), *resources::gameboard))
{
if (!is_allowed_enemy(*j)) {
continue;
@ -288,7 +288,7 @@ void aspect_attacks_base::do_attack_analysis(
}
// No surround bonus if target is skirmisher
if (!itor->get_ability_bool("skirmisher"))
if (!itor->get_ability_bool("skirmisher", *resources::gameboard))
surround_bonus = 1.2;
}
@ -360,7 +360,7 @@ int aspect_attacks_base::rate_terrain(const unit& u, const map_location& loc)
const int neutral_village_value = 10;
const int enemy_village_value = 15;
if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate",loc) == false) {
if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate", loc, *resources::gameboard) == false) {
rating += healing_value;
}

View file

@ -1342,7 +1342,7 @@ double get_healing_phase::evaluate()
if(u.side() == get_side() &&
(u.max_hitpoints() - u.hitpoints() >= game_config::poison_amount/2
|| u.get_state(unit::STATE_POISONED)) &&
!u.get_ability_bool("regenerate"))
!u.get_ability_bool("regenerate", *resources::gameboard))
{
// Look for the village which is the least vulnerable to enemy attack.
typedef std::multimap<map_location,map_location>::const_iterator Itor;

View file

@ -81,7 +81,7 @@ int default_ai_context_impl::count_free_hexes_in_castle(const map_location &loc,
ret += count_free_hexes_in_castle(adj[n], checked_hexes);
if (u == units_.end()
|| (current_team().is_enemy(u->side())
&& u->invisible(adj[n]))
&& u->invisible(adj[n], *resources::gameboard))
|| ((&resources::gameboard->teams()[u->side() - 1]) == &current_team()
&& u->movement_left() > 0)) {
ret += 1;
@ -109,7 +109,7 @@ int default_ai_context_impl::rate_terrain(const unit& u, const map_location& loc
const int neutral_village_value = 10;
const int enemy_village_value = 15;
if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate",loc) == false) {
if(map_.gives_healing(terrain) && u.get_ability_bool("regenerate", loc, *resources::gameboard) == false) {
rating += healing_value;
}
@ -228,7 +228,7 @@ std::vector<target> default_ai_context_impl::find_targets(const move_map& enemy_
for(u = units_.begin(); u != units_.end(); ++u) {
//is a visible enemy leader
if (u->can_recruit() && current_team().is_enemy(u->side())
&& !u->invisible(u->get_location())) {
&& !u->invisible(u->get_location(), *resources::gameboard)) {
assert(map_.on_board(u->get_location()));
LOG_AI << "found enemy leader (side: " << u->side() << ") target... " << u->get_location() << " with value: " << get_leader_value() << "\n";
targets.push_back(target(u->get_location(), get_leader_value(), target::TYPE::LEADER));

View file

@ -210,7 +210,7 @@ void attack_map_callable::collect_possible_attacks(std::vector<variant>& vars, m
/* if tile is occupied by friendly or petrified/invisible unit */
if (!ai_.current_team().is_enemy(unit->side()) ||
unit->incapacitated() ||
unit->invisible(unit->get_location()))
unit->invisible(unit->get_location(), *resources::gameboard))
continue;
/* add attacks with default weapon */
attack_callable* item = new attack_callable(attacker_location, attack_position, adj[n], -1);

View file

@ -19,6 +19,7 @@
#include "ai/formula/ai.hpp"
#include "ai/formula/candidates.hpp"
#include "game_board.hpp"
#include "log.hpp"
#include "resources.hpp"
@ -164,7 +165,7 @@ void attack_candidate_action::evaluate(ai::formula_ai* ai, unit_map& units)
}
} else
{
if (ai->current_team().is_enemy(i->side()) && !i->incapacitated() && !i->invisible(i->get_location())) {
if (ai->current_team().is_enemy(i->side()) && !i->incapacitated() && !i->invisible(i->get_location(), *resources::gameboard)) {
enemy_res.push_back(variant(new unit_callable(*i)));
}
}

View file

@ -2102,7 +2102,9 @@ void display::draw_minimap()
draw_minimap_units();
#else
if(minimap_ == nullptr || minimap_->w > area.w || minimap_->h > area.h) {
minimap_ = image::getMinimap(area.w, area.h, get_map(), &dc_->teams()[currentTeam_], (selectedHex_.valid() && !is_blindfolded()) ? &reach_map_ : nullptr);
minimap_ = image::getMinimap(area.w, area.h, get_map(),
dc_->teams().empty() ? nullptr : &dc_->teams()[currentTeam_],
(selectedHex_.valid() && !is_blindfolded()) ? &reach_map_ : nullptr);
if(minimap_ == nullptr) {
return;
}
@ -2159,7 +2161,7 @@ void display::draw_minimap_units()
for(unit_map::const_iterator u = dc_->units().begin(); u != dc_->units().end(); ++u) {
if (fogged(u->get_location()) ||
(dc_->teams()[currentTeam_].is_enemy(u->side()) &&
u->invisible(u->get_location())) ||
u->invisible(u->get_location(), *dc_)) ||
u->get_hidden()) {
continue;
}
@ -2830,6 +2832,12 @@ void display::draw_invalidated() {
}
invalidated_hexes_ += invalidated_.size();
if (dc_->teams().empty())
{
// The unit drawer can't function without teams
return;
}
unit_drawer drawer = unit_drawer(*this, energy_bar_rects_);
for (const map_location& loc : invalidated_) {

View file

@ -46,7 +46,7 @@ bool display_context::would_be_discovered(const map_location & loc, int side_num
if(see_all) {
return true;
} else if (!teams()[side_num-1].fogged(u_loc)
&& !u.invisible(u_loc, true)) {
&& !u.invisible(u_loc, *this, true)) {
return true;
}
}
@ -58,7 +58,7 @@ const unit * display_context::get_visible_unit(const map_location & loc, const t
{
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, map(), see_all)) {
if (!u.valid() || !u->is_visible_to_team(current_team, map(), *this, see_all)) {
return nullptr;
}
return &*u;

View file

@ -175,7 +175,7 @@ unit_map::iterator game_board::find_visible_unit(const map_location &loc,
{
if (!map_->on_board(loc)) return units_.end();
unit_map::iterator u = units_.find(loc);
if (!u.valid() || !u->is_visible_to_team(current_team, *map_, see_all))
if (!u.valid() || !u->is_visible_to_team(current_team, *map_, *this, see_all))
return units_.end();
return u;
}
@ -184,7 +184,7 @@ bool game_board::has_visible_unit(const map_location & loc, const team& current_
{
if (!map_->on_board(loc)) return false;
unit_map::const_iterator u = units_.find(loc);
if (!u.valid() || !u->is_visible_to_team(current_team, *map_, see_all))
if (!u.valid() || !u->is_visible_to_team(current_team, *map_, *this, see_all))
return false;
return true;
}

View file

@ -33,7 +33,9 @@
#include "gui/widgets/window.hpp"
#include "display.hpp"
#include "formatter.hpp"
#include "game_board.hpp"
#include "marked-up_text.hpp"
#include "resources.hpp"
#include "units/map.hpp"
#include "units/ptr.hpp"
#include "units/unit.hpp"
@ -149,7 +151,7 @@ void tunit_list::pre_show(twindow& window)
// NOTE: this needs to be done *after* the row is added
// TODO: show custom statuses
if(!unit->get_state(unit::STATE_PETRIFIED)) {
find_widget<timage>(row_grid, "unit_status_slowed", false).set_visible(twidget::tvisible::invisible);
find_widget<timage>(row_grid, "unit_status_petrified", false).set_visible(twidget::tvisible::invisible);
}
if(!unit->get_state(unit::STATE_POISONED)) {
@ -157,11 +159,11 @@ void tunit_list::pre_show(twindow& window)
}
if(!unit->get_state(unit::STATE_SLOWED)) {
find_widget<timage>(row_grid, "unit_status_invisible", false).set_visible(twidget::tvisible::invisible);
find_widget<timage>(row_grid, "unit_status_slowed", false).set_visible(twidget::tvisible::invisible);
}
if(!unit->invisible(unit->get_location(), false)) {
find_widget<timage>(row_grid, "unit_status_petrified", false).set_visible(twidget::tvisible::invisible);
if(!unit->invisible(unit->get_location(), *resources::gameboard, false)) {
find_widget<timage>(row_grid, "unit_status_invisible", false).set_visible(twidget::tvisible::invisible);
}
}

View file

@ -435,7 +435,7 @@ void menu_handler::show_enemy_moves(bool ignore_units, int side_num)
// Compute enemy movement positions
for(unit_map::iterator u = units().begin(); u != units().end(); ++u) {
bool invisible = u->invisible(u->get_location());
bool invisible = u->invisible(u->get_location(), gui_->get_disp_context());
if (teams()[side_num - 1].is_enemy(u->side()) &&
!gui_->fogged(u->get_location()) && !u->incapacitated() && !invisible)
@ -1293,7 +1293,7 @@ void menu_handler::do_search(const std::string& new_search)
last_search_.begin(), last_search_.end(),
chars_equal_insensitive) != name.end()) {
if (!teams()[gui_->viewing_team()].is_enemy(ui->side()) ||
!ui->invisible(ui->get_location())) {
!ui->invisible(ui->get_location(), gui_->get_disp_context())) {
found = true;
}
}

View file

@ -779,7 +779,7 @@ void mouse_handler::select_hex(const map_location& hex, const bool browse, const
clicked_location.destinations.insert(hex);
for(unit_map::iterator u = pc_.gamestate().board_.units_.begin(); u != pc_.gamestate().board_.units_.end(); ++u) {
bool invisible = u->invisible(u->get_location());
bool invisible = u->invisible(u->get_location(), gui_->get_disp_context());
if (!gui_->fogged(u->get_location()) && !u->incapacitated() && !invisible)
{
@ -1097,7 +1097,7 @@ void mouse_handler::show_attack_options(const unit_map::const_iterator &u)
// (Visible to current team, not necessarily the unit's team.)
if (!pc_.get_map_const().on_board(loc)) continue;
unit_map::const_iterator i = pc_.gamestate().board_.units().find(loc);
if ( !i || !i->is_visible_to_team(cur_team, pc_.gamestate().board_.map(), false) )
if ( !i || !i->is_visible_to_team(cur_team, pc_.gamestate().board_.map(), gui_->get_disp_context(), false) )
continue;
const unit &target = *i;
// Can only attack non-petrified enemies.
@ -1119,7 +1119,7 @@ bool mouse_handler::unit_in_cycle(unit_map::const_iterator it)
return false;
if (current_team().is_enemy(int(gui().viewing_team()+1)) &&
it->invisible(it->get_location()))
it->invisible(it->get_location(), gui().get_disp_context()))
return false;
if (it->get_hidden())

View file

@ -401,7 +401,7 @@ static void find_routes(
if ( skirmisher && next.moves_left > 0 &&
enemy_zoc(*current_team, next_hex, *viewing_team, see_all) &&
!skirmisher->get_ability_bool("skirmisher", next_hex) ) {
!skirmisher->get_ability_bool("skirmisher", next_hex, *resources::gameboard) ) {
next.moves_left = 0;
}
}
@ -656,7 +656,7 @@ marked_route mark_route(const plain_route &rt)
++turns;
bool invisible = u.invisible(*i,false);
bool invisible = u.invisible(*i, *resources::gameboard, false);
res.marks[*i] = marked_route::mark(turns, zoc, capture, invisible);
@ -669,7 +669,7 @@ marked_route mark_route(const plain_route &rt)
}
zoc = enemy_zoc(unit_team, *(i + 1), viewing_team)
&& !u.get_ability_bool("skirmisher", *(i+1));
&& !u.get_ability_bool("skirmisher", *(i+1), *resources::gameboard);
if (zoc) {
movement = 0;
@ -752,7 +752,7 @@ double shortest_path_calculator::cost(const map_location& loc, const double so_f
// check ZoC
if (!ignore_unit_ && remaining_movement != terrain_cost
&& enemy_zoc(teams_[unit_.side()-1], loc, viewing_team_, see_all_)
&& !unit_.get_ability_bool("skirmisher", loc)) {
&& !unit_.get_ability_bool("skirmisher", loc, *resources::gameboard)) {
// entering ZoC cost all remaining MP
move_cost += remaining_movement;
} else {

View file

@ -236,7 +236,7 @@ const teleport_map get_teleport_locations(const unit &u,
{
std::vector<teleport_group> groups;
if (u.get_ability_bool("teleport")) {
if (u.get_ability_bool("teleport", *resources::gameboard)) {
for (const unit_ability & teleport : u.get_abilities("teleport")) {
const int tunnel_count = (teleport.first)->child_count("tunnel");
for(int i = 0; i < tunnel_count; ++i) {

View file

@ -623,7 +623,7 @@ void play_controller::tab()
for (const unit& u : gamestate().board_.units()){
const map_location& loc = u.get_location();
if(!gui_->fogged(loc) &&
!(gamestate().board_.teams()[gui_->viewing_team()].is_enemy(u.side()) && u.invisible(loc)))
!(gamestate().board_.teams()[gui_->viewing_team()].is_enemy(u.side()) && u.invisible(loc, gui_->get_disp_context())))
dictionary.insert(u.name());
}
//TODO List map labels

View file

@ -299,7 +299,7 @@ static config unit_status(reports::context & rc, const unit* u)
if (!u) return config();
config res;
map_location displayed_unit_hex = rc.screen().displayed_unit_hex();
if (rc.map().on_board(displayed_unit_hex) && u->invisible(displayed_unit_hex)) {
if (rc.map().on_board(displayed_unit_hex) && u->invisible(displayed_unit_hex, rc.dc())) {
add_status(res, "misc/invisible.png", N_("invisible: "),
N_("This unit is invisible. It cannot be seen or attacked by enemy units."));
}
@ -762,7 +762,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res
continue;
const map_location &loc = enemy.get_location();
if (viewing_team.fogged(loc) ||
(viewing_team.is_enemy(enemy.side()) && enemy.invisible(loc)))
(viewing_team.is_enemy(enemy.side()) && enemy.invisible(loc, rc.dc())))
continue;
bool new_type = seen_types.insert(enemy.type_id()).second;
if (new_type) {

View file

@ -2300,11 +2300,11 @@ static int intf_unit_defense(lua_State *L)
* - Arg 2: string.
* - Ret 1: boolean.
*/
static int intf_unit_ability(lua_State *L)
int game_lua_kernel::intf_unit_ability(lua_State *L)
{
const unit& u = luaW_checkunit(L, 1);
char const *m = luaL_checkstring(L, 2);
lua_pushboolean(L, u.get_ability_bool(m));
lua_pushboolean(L, u.get_ability_bool(m, board()));
return 1;
}
@ -4087,7 +4087,6 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
{ "remove_modifications", &intf_remove_modifications },
{ "set_music", &intf_set_music },
{ "transform_unit", &intf_transform_unit },
{ "unit_ability", &intf_unit_ability },
{ "unit_defense", &intf_unit_defense },
{ "unit_movement_cost", &intf_unit_movement_cost },
{ "unit_vision_cost", &intf_unit_vision_cost },
@ -4186,6 +4185,7 @@ game_lua_kernel::game_lua_kernel(CVideo * video, game_state & gs, play_controlle
{ "synchronize_choice", &intf_synchronize_choice },
{ "synchronize_choices", &intf_synchronize_choices },
{ "teleport", &dispatch<&game_lua_kernel::intf_teleport > },
{ "unit_ability", &dispatch<&game_lua_kernel::intf_unit_ability > },
{ "view_locked", &dispatch<&game_lua_kernel::intf_view_locked > },
{ "place_shroud", &dispatch2<&game_lua_kernel::intf_shroud_op, true > },
{ "remove_shroud", &dispatch2<&game_lua_kernel::intf_shroud_op, false > },
@ -4385,7 +4385,7 @@ int game_lua_kernel::return_unit_method(lua_State *L, char const *m) {
{"movement", intf_unit_movement_cost},
{"vision", intf_unit_vision_cost},
{"jamming", intf_unit_jamming_cost},
{"ability", intf_unit_ability},
{"ability", &dispatch<&game_lua_kernel::intf_unit_ability>},
{"transform", intf_transform_unit},
{"select", &dispatch<&game_lua_kernel::intf_select_unit>},
};

View file

@ -89,6 +89,7 @@ class game_lua_kernel : public lua_kernel_base
int intf_set_side_variable(lua_State *L);
int intf_highlight_hex(lua_State *L);
int intf_is_enemy(lua_State *L);
int intf_unit_ability(lua_State *L);
int intf_view_locked(lua_State *L);
int intf_lock_view(lua_State *L);
int intf_get_terrain(lua_State *L);

View file

@ -222,7 +222,7 @@ const time_of_day tod_manager::get_illuminated_time_of_day(const unit_map & unit
for ( size_t i = 0; i != 7; ++i ) {
const unit_map::const_iterator itor = units.find(locs[i]);
if (itor != units.end() &&
itor->get_ability_bool("illuminates") &&
itor->get_ability_bool("illuminates", *resources::gameboard) &&
!itor->incapacitated())
{
unit_ability_list illum = itor->get_abilities("illuminates");

View file

@ -17,6 +17,7 @@
* Manage unit-abilities, like heal, cure, and weapon_specials.
*/
#include "display_context.hpp"
#include "game_board.hpp"
#include "log.hpp"
#include "resources.hpp"
@ -126,10 +127,8 @@ bool affects_side(const config& cfg, const std::vector<team>& teams, size_t side
}
bool unit::get_ability_bool(const std::string& tag_name, const map_location& loc) const
bool unit::get_ability_bool(const std::string& tag_name, const map_location& loc, const display_context& dc) const
{
assert(resources::gameboard);
for (const config &i : this->abilities_.child_range(tag_name)) {
if (ability_active(tag_name, i, loc) &&
ability_affects_self(tag_name, i, loc))
@ -153,7 +152,7 @@ bool unit::get_ability_bool(const std::string& tag_name, const map_location& loc
if ( &*it == this )
continue;
for (const config &j : it->abilities_.child_range(tag_name)) {
if (affects_side(j, resources::gameboard->teams(), side(), it->side()) &&
if (affects_side(j, dc.teams(), side(), it->side()) &&
it->ability_active(tag_name, j, adjacent[i]) &&
ability_affects_adjacent(tag_name, j, i, loc, *it))
{

View file

@ -76,7 +76,7 @@ void unit_drawer::redraw_unit (const unit & u) const
std::string ellipse=u.image_ellipse();
if ( hidden || is_blindfolded || !u.is_visible_to_team(viewing_team_ref,map, show_everything) )
if ( hidden || is_blindfolded || !u.is_visible_to_team(viewing_team_ref, map, dc, show_everything) )
{
ac.clear_haloes();
if(ac.anim_) {
@ -102,7 +102,7 @@ void unit_drawer::redraw_unit (const unit & u) const
// instead use -1.0 (as in "negative depth", it will be ignored by rendering)
params.submerge= is_flying ? -1.0 : terrain_info.unit_submerge();
if (u.invisible(loc) &&
if (u.invisible(loc, dc) &&
params.highlight_ratio > 0.5) {
params.highlight_ratio = 0.5;
}

View file

@ -500,7 +500,7 @@ bool basic_unit_filter_impl::internal_matches_filter(const unit & u, const map_l
bool found = false;
for (const int viewer : viewers) {
bool fogged = fc_.get_disp_context().teams()[viewer - 1].fogged(loc);
bool hiding = u.invisible(loc/*, false(?) */);
bool hiding = u.invisible(loc, fc_.get_disp_context());
bool unit_hidden = fogged || hiding;
if (vision["visible"].to_bool(true) != unit_hidden) {
found = true;

View file

@ -267,7 +267,7 @@ void unit_mover::start(unit_ptr u)
disp_->invalidate(path_[0]);
// If the unit can be seen here by the viewing side:
if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[0]) ) {
if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[0], disp_->get_disp_context()) ) {
// Scroll to the path, but only if it fully fits on screen.
// If it does not fit we might be able to do a better scroll later.
disp_->scroll_to_tiles(path_, game_display::ONSCREEN, true, true, 0.0, false);
@ -336,8 +336,8 @@ void unit_mover::proceed_to(unit_ptr u, size_t path_index, bool update, bool wai
for ( ; current_ < path_index; ++current_ )
// If the unit can be seen by the viewing side while making this step:
if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[current_]) ||
!temp_unit_ptr_->invisible(path_[current_+1]) )
if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[current_], disp_->get_disp_context()) ||
!temp_unit_ptr_->invisible(path_[current_+1], disp_->get_disp_context()) )
{
// Wait for the previous step to complete before drawing the next one.
wait_for_anims();

View file

@ -2280,7 +2280,7 @@ void unit::apply_modifications()
max_experience_ = std::max<int>(1, (max_experience_ * exp_accel + 50)/100);
}
bool unit::invisible(const map_location& loc, bool see_all) const
bool unit::invisible(const map_location& loc, const display_context& dc, bool see_all) const
{
if (loc != get_location()) {
DBG_UT << "unit::invisible called: id = " << id() << " loc = " << loc << " get_loc = " << get_location() << std::endl;
@ -2305,7 +2305,7 @@ bool unit::invisible(const map_location& loc, bool see_all) const
// Test hidden status
static const std::string hides("hides");
bool is_inv = get_ability_bool(hides,loc);
bool is_inv = get_ability_bool(hides, loc, dc);
if(is_inv){
is_inv = (resources::gameboard ? !resources::gameboard->would_be_discovered(loc, side_,see_all) : true);
}
@ -2322,14 +2322,14 @@ bool unit::invisible(const map_location& loc, bool see_all) const
}
bool unit::is_visible_to_team(team const& team, gamemap const& map, bool const see_all) const
bool unit::is_visible_to_team(team const& team, gamemap const& map, display_context const& dc, bool const see_all) const
{
map_location const& loc = get_location();
if (!map.on_board(loc))
return false;
if (see_all)
return true;
if (team.is_enemy(side()) && invisible(loc))
if (team.is_enemy(side()) && invisible(loc, dc))
return false;
// allied planned moves are also visible under fog. (we assume that fake units on the map are always whiteboard markers)
if (!team.is_enemy(side()) && underlying_id_.is_fake())

View file

@ -25,6 +25,7 @@
#include "units/id.hpp"
class display;
class display_context;
class gamemap;
struct SDL_Color;
class team;
@ -366,13 +367,13 @@ public:
* Returns true if the unit is currently under effect by an ability with this given TAG NAME.
* This means that the ability could be owned by the unit itself, or by an adjacent unit.
*/
bool get_ability_bool(const std::string& tag_name, const map_location& loc) const;
bool get_ability_bool(const std::string& tag_name, const map_location& loc, const display_context& dc) const;
/**
* Returns true if the unit is currently under effect by an ability with this given TAG NAME.
* This means that the ability could be owned by the unit itself, or by an adjacent unit.
*/
bool get_ability_bool(const std::string &tag_name) const
{ return get_ability_bool(tag_name, loc_); }
bool get_ability_bool(const std::string &tag_name, const display_context& dc) const
{ return get_ability_bool(tag_name, loc_, dc); }
unit_ability_list get_abilities(const std::string &tag_name, const map_location& loc) const;
unit_ability_list get_abilities(const std::string &tag_name) const
{ return get_abilities(tag_name, loc_); }
@ -389,9 +390,9 @@ public:
void generate_name();
// Only see_all=true use caching
bool invisible(const map_location& loc, bool see_all=true) const;
bool invisible(const map_location& loc, const display_context& dc, bool see_all = true) const;
bool is_visible_to_team(team const& team, gamemap const & map , bool const see_all = true) const;
bool is_visible_to_team(team const& team, gamemap const& map , display_context const& dc, bool const see_all = true) const;
/** Mark this unit as clone so it can be inserted to unit_map
* @returns self (for convenience)

View file

@ -68,7 +68,7 @@ void mapbuilder::pre_build()
//Remove any unit the current side cannot see to avoid their detection by planning
//Units will be restored to the unit map by destruction of removers_
if(!on_current_side && !u.is_visible_to_team(resources::gameboard->teams()[viewer_team()], resources::gameboard->map(), false)) {
if(!on_current_side && !u.is_visible_to_team(resources::gameboard->teams()[viewer_team()], resources::gameboard->map(), *resources::gameboard, false)) {
removers_.push_back(new temporary_unit_remover(*resources::units, u.get_location()));
//Don't do anything else to the removed unit!