/** * Clears shroud from a single location. * This also records sighted events for later firing. * * In a few cases, this will also clear corner hexes that otherwise would * not normally get cleared. * @param tm The team whose fog/shroud is affected. * @param loc The location to clear. * @param view_loc The location viewer is assumed at (for sighted events). * @param event_non_loc The unit at this location cannot be sighted * (used to prevent a unit from sighting itself). * @param viewer_id The underlying ID of the unit doing the sighting (for events). * @param check_units If false, there is no checking for an uncovered unit. * @param enemy_count Incremented if an enemy is uncovered. * @param friend_count Incremented if a friend is uncovered. * @param spectator Will be told if a unit is uncovered. * * @return whether or not information was uncovered (i.e. returns true if * the specified location was fogged/ shrouded under shared vision/maps). */ bool shroud_clearer::clear_loc(team &tm, const map_location &loc, const map_location &view_loc, const map_location &event_non_loc, std::size_t viewer_id, bool check_units, std::size_t &enemy_count, std::size_t &friend_count, move_unit_spectator * spectator) { const gamemap &map = resources::gameboard->map(); // This counts as clearing a tile for the return value if it is on the // board and currently fogged under shared vision. (No need to explicitly // check for shrouded since shrouded implies fogged.) bool was_fogged = tm.fogged(loc); bool result = was_fogged && map.on_board(loc); // Clear the border as well as the board, so that the half-hexes // at the edge can also be cleared of fog/shroud. if ( map.on_board_with_border(loc) ) { // Both functions should be executed so don't use || which // uses short-cut evaluation. // (This is different than the return value because shared vision does // not apply here.) if ( tm.clear_shroud(loc) | tm.clear_fog(loc) ) { // If we are near a corner, the corner might also need to be cleared. // This happens at the lower-left corner and at either the upper- or // lower- right corner (depending on the width). // Lower-left corner: if ( loc.x == 0 && loc.y == map.h()-1 ) { const map_location corner(-1, map.h()); tm.clear_shroud(corner); tm.clear_fog(corner); } // Lower-right corner, odd width: else if ( is_odd(map.w()) && loc.x == map.w()-1 && loc.y == map.h()-1 ) { const map_location corner(map.w(), map.h()); tm.clear_shroud(corner); tm.clear_fog(corner); } // Upper-right corner, even width: else if ( is_even(map.w()) && loc.x == map.w()-1 && loc.y == 0) { const map_location corner(map.w(), -1); tm.clear_shroud(corner); tm.clear_fog(corner); } } } // Possible screen invalidation. if ( was_fogged ) { display::get_singleton()->invalidate(loc); // Need to also invalidate adjacent hexes to get rid of the // "fog edge" graphics. adjacent_loc_array_t adjacent; get_adjacent_tiles(loc, adjacent.data()); for (unsigned i = 0; i < adjacent.size(); ++i ) display::get_singleton()->invalidate(adjacent[i]); } // Check for units? if ( result && check_units && loc != event_non_loc ) { // Uncovered a unit? unit_map::const_iterator sight_it = resources::gameboard->find_visible_unit(loc, tm); if ( sight_it.valid() ) { record_sighting(*sight_it, loc, viewer_id, view_loc); // Track this? if ( !sight_it->get_state(unit::STATE_PETRIFIED) ) { if ( tm.is_enemy(sight_it->side()) ) { ++enemy_count; if ( spectator ) spectator->add_seen_enemy(sight_it); } else { ++friend_count; if ( spectator ) spectator->add_seen_friend(sight_it); } } } } return result; }