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:
parent
206096cc1e
commit
7573678201
31 changed files with 80 additions and 68 deletions
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]) == ¤t_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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>},
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!
|
||||
|
|
Loading…
Add table
Reference in a new issue