add filter_context class, use in unit_filter

The filter context is, game_board + tod manager.
game_display can (and now does) implement this interface,
also game_state. This permits both animations and engine
components to use it.
This commit is contained in:
Chris Beck 2014-07-03 05:30:47 -04:00
parent d803cde06a
commit d86b59f08a
27 changed files with 145 additions and 75 deletions

View file

@ -25,6 +25,7 @@
#include "../config.hpp"
#include "../config_assign.hpp"
#include "../filter_context.hpp"
#include "../game_board.hpp"
#include "../game_display.hpp"
#include "../game_events/pump.hpp"
@ -434,7 +435,7 @@ namespace { // Helpers for get_recalls()
if ( unit_filter::matches_filter( rfilter,
recall_unit,
map_location::null_location(),
resources::gameboard) )
resources::filter_con) )
{
result.push_back(recall_unit_ptr);
if ( already_added != NULL )
@ -537,7 +538,7 @@ namespace { // Helpers for check_recall_location()
if ( !unit_filter::matches_filter(rfilter,
recall_unit,
map_location::null_location(),
resources::gameboard) )
resources::filter_con) )
return RECRUIT_NO_ABLE_LEADER;
// Make sure the unit is on a keep.

View file

@ -135,7 +135,7 @@ void target_unit_goal::add_targets(std::back_insert_iterator< std::vector< targe
//find the enemy leaders and explicit targets
BOOST_FOREACH(const unit &u, *resources::units) {
if (unit_filter::matches_filter(vconfig(criteria), u, u.get_location(), resources::gameboard)) {
if (unit_filter::matches_filter(vconfig(criteria), u, u.get_location(), resources::filter_con)) {
LOG_AI_GOAL << "found explicit target unit at ... " << u.get_location() << " with value: " << value() << "\n";
*target_list = target(u.get_location(), value(), target::EXPLICIT);
}
@ -264,7 +264,7 @@ void protect_goal::add_targets(std::back_insert_iterator< std::vector< target >
continue;
}
//TODO: we will protect hidden units, by not testing for invisibility to current side
if (unit_filter::matches_filter(vconfig(criteria), u, u.get_location(), resources::gameboard)) {
if (unit_filter::matches_filter(vconfig(criteria), u, u.get_location(), resources::filter_con)) {
DBG_AI_GOAL << "side " << get_side() << ": in " << goal_type << ": " << u.get_location() << " should be protected\n";
items.insert(u.get_location());
}

View file

@ -25,6 +25,7 @@
#include "../manager.hpp"
#include "../../actions/attack.hpp"
#include "../../attack_prediction.hpp"
#include "../../filter_context.hpp"
#include "../../game_board.hpp"
#include "../../game_display.hpp"
#include "../../log.hpp"
@ -252,7 +253,7 @@ void recruitment::execute() {
BOOST_FOREACH(const unit_const_ptr & recall, current_team().recall_list()) {
// Check if this leader is allowed to recall this unit.
vconfig filter = vconfig(leader->recall_filter());
if (!unit_filter::matches_filter(filter, *recall, map_location::null_location(), resources::gameboard)) {
if (!unit_filter::matches_filter(filter, *recall, map_location::null_location(), resources::filter_con)) {
continue;
}
data.recruits.insert(recall->type_id());
@ -477,7 +478,7 @@ const std::string* recruitment::get_appropriate_recall(const std::string& type,
}
// Check if this leader is allowed to recall this unit.
vconfig filter = vconfig(leader_data.leader->recall_filter());
if (!unit_filter::matches_filter(filter, *recall_unit, map_location::null_location(), resources::gameboard)) {
if (!unit_filter::matches_filter(filter, *recall_unit, map_location::null_location(), resources::filter_con)) {
LOG_AI_RECRUITMENT << "Refused recall because of filter: " << recall_unit->id() << "\n";
continue;
}

View file

@ -76,7 +76,7 @@ boost::shared_ptr<attacks_vector> aspect_attacks::analyze_targets() const
std::vector<map_location> unit_locs;
for(unit_map::const_iterator i = units_.begin(); i != units_.end(); ++i) {
if (i->side() == get_side() && i->attacks_left() && !(i->can_recruit() && get_passive_leader())) {
if (!unit_filter::matches_filter(vconfig(filter_own_), *i, i->get_location(), resources::gameboard)) {
if (!unit_filter::matches_filter(vconfig(filter_own_), *i, i->get_location(), resources::filter_con)) {
continue;
}
unit_locs.push_back(i->get_location());
@ -99,7 +99,7 @@ boost::shared_ptr<attacks_vector> aspect_attacks::analyze_targets() const
if (current_team().is_enemy(j->side()) && !j->incapacitated() &&
!j->invisible(j->get_location()))
{
if (!unit_filter::matches_filter(vconfig(filter_enemy_), *j, j->get_location(), resources::gameboard)) {
if (!unit_filter::matches_filter(vconfig(filter_enemy_), *j, j->get_location(), resources::filter_con)) {
continue;
}
map_location adjacent[6];

View file

@ -416,6 +416,16 @@ const time_of_day & display::get_time_of_day(const map_location& /*loc*/) const
return tod;
}
/**
* Display objects don't hold a tod maanger, instead game_display objects do. If the base version of this method is called,
* try to get it from resources and use an assert to check for failure.
*/
const tod_manager & display::get_tod_man() const
{
assert(resources::tod_manager);
return *resources::tod_manager;
}
void display::update_tod() {
const time_of_day& tod = get_time_of_day();
tod_color col = color_adjust_ + tod.color;

View file

@ -49,6 +49,7 @@ namespace wb {
#include "animated.hpp"
#include "display_context.hpp"
#include "filter_context.hpp"
#include "font.hpp"
#include "image.hpp" //only needed for enums (!)
#include "key.hpp"
@ -71,7 +72,7 @@ namespace wb {
class gamemap;
class display
class display : public filter_context
{
public:
display(const display_context * dc, CVideo& video, boost::weak_ptr<wb::manager> wb,
@ -164,6 +165,7 @@ public:
void change_display_context(const display_context * dc);
const display_context & get_disp_context() const { return *dc_; }
virtual const tod_manager & get_tod_man() const; //!< This is implemented properly in game_display. The display:: impl could be pure virtual here but we decide not to.
void reset_halo_manager();
void reset_halo_manager(halo::manager & hm);

43
src/filter_context.hpp Normal file
View file

@ -0,0 +1,43 @@
/*
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
*
* This class is an abstract base class which represents a display context
* (game map, units, and teams) together with a TOD manager. This, plus
* a lua kernel (currently a singleton) is sufficient to evaluate filters.
*
**/
#ifndef FILTER_CONTEXT_HPP_INCLUDED
#define FILTER_CONTEXT_HPP_INCLUDED
#include <vector>
class display_context;
class tod_manager;
class filter_context {
public:
// accessors
virtual const display_context & get_disp_context() const = 0;
virtual const tod_manager & get_tod_man() const = 0;
// Dtor
virtual ~filter_context() {}
};
#endif

View file

@ -60,7 +60,7 @@ class game_board : public display_context {
friend class play_controller;
friend class events::mouse_handler;
friend class events::menu_handler;
friend struct game_state;
friend class game_state;
/**
* Temporary unit move structs:

View file

@ -130,6 +130,8 @@ public:
bool has_time_area() const;
const tod_manager & get_tod_man() const { return tod_manager_; } //<! Allows this class to properly implement filter context, used for animations
protected:
/**
* game_display pre_draw does specific things related e.g. to unit rendering

View file

@ -406,7 +406,7 @@ namespace { // Support functions
speaker = units->find(event_info.loc2);
} else if(speaker_str != "narrator") {
for(speaker = units->begin(); speaker != units->end(); ++speaker){
if ( unit_filter::matches_filter(cfg,*speaker, resources::gameboard) )
if ( unit_filter::matches_filter(cfg,*speaker, resources::filter_con) )
break;
}
}
@ -779,7 +779,7 @@ WML_HANDLER_FUNCTION(heal_unit, event_info, cfg)
std::vector<unit*> healers;
if (!healers_filter.null()) {
BOOST_FOREACH(unit& u, *units) {
if ( unit_filter::matches_filter(healers_filter,u, resources::gameboard) && u.has_ability_type("heals") ) {
if ( unit_filter::matches_filter(healers_filter,u, resources::filter_con) && u.has_ability_type("heals") ) {
healers.push_back(&u);
}
}
@ -800,7 +800,7 @@ WML_HANDLER_FUNCTION(heal_unit, event_info, cfg)
u = units->find(event_info.loc1);
if(!u.valid()) return;
}
else if ( !unit_filter::matches_filter(healed_filter,*u, resources::gameboard) ) continue;
else if ( !unit_filter::matches_filter(healed_filter,*u, resources::filter_con) ) continue;
int heal_amount = u->max_hitpoints() - u->hitpoints();
if(amount.blank() || amount == "full") u->set_hitpoints(u->max_hitpoints());
@ -859,7 +859,7 @@ WML_HANDLER_FUNCTION(kill, event_info, cfg)
secondary_unit = false;
for(unit_map::const_unit_iterator unit = resources::units->begin();
unit != resources::units->end(); ++unit) {
if ( unit_filter::matches_filter(cfg.child("secondary_unit"), *unit, resources::gameboard) )
if ( unit_filter::matches_filter(cfg.child("secondary_unit"), *unit, resources::filter_con) )
{
killer_loc = entity_location(*unit);
secondary_unit = true;
@ -874,7 +874,7 @@ WML_HANDLER_FUNCTION(kill, event_info, cfg)
//Find all the dead units first, because firing events ruins unit_map iteration
std::vector<unit *> dead_men_walking;
BOOST_FOREACH(unit & u, *resources::units){
if ( unit_filter::matches_filter(cfg,u, resources::gameboard) ) {
if ( unit_filter::matches_filter(cfg,u, resources::filter_con) ) {
dead_men_walking.push_back(&u);
}
}
@ -948,7 +948,7 @@ WML_HANDLER_FUNCTION(kill, event_info, cfg)
{
for(std::vector<unit_ptr>::iterator j = pi->recall_list().begin(); j != pi->recall_list().end();) { //TODO: This block is really messy, cleanup somehow...
scoped_recall_unit auto_store("this_unit", pi->save_id(), j - pi->recall_list().begin());
if (unit_filter::matches_filter(cfg, *(*j), map_location(), resources::gameboard)) {
if (unit_filter::matches_filter(cfg, *(*j), map_location(), resources::filter_con)) {
j = pi->recall_list().erase(j);
} else {
++j;
@ -1416,7 +1416,7 @@ WML_HANDLER_FUNCTION(object, event_info, cfg)
map_location loc;
if(!filter.null()) {
BOOST_FOREACH(const unit &u, *resources::units) {
if ( unit_filter::matches_filter(filter,u, resources::gameboard) ) {
if ( unit_filter::matches_filter(filter,u, resources::filter_con) ) {
loc = u.get_location();
break;
}
@ -1431,7 +1431,7 @@ WML_HANDLER_FUNCTION(object, event_info, cfg)
std::string command_type = "then";
if ( u != resources::units->end() && (filter.null() || unit_filter::matches_filter(filter,*u, resources::gameboard)) )
if ( u != resources::units->end() && (filter.null() || unit_filter::matches_filter(filter,*u, resources::filter_con)) )
{
///@deprecated This can be removed (and a proper duration=level implemented) after 1.11.2
/// Don't forget to remove it from wmllint too!
@ -1546,7 +1546,7 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
for(std::vector<unit_ptr>::iterator u = avail.begin(); u != avail.end(); ++u) {
DBG_NG << "checking unit against filter...\n";
scoped_recall_unit auto_store("this_unit", player_id, u - avail.begin());
if (unit_filter::matches_filter(unit_filter, *(*u), map_location(), resources::gameboard)) {
if (unit_filter::matches_filter(unit_filter, *(*u), map_location(), resources::filter_con)) {
DBG_NG << (*u)->id() << " matched the filter...\n";
const unit_ptr to_recruit = *u;
const unit* pass_check = to_recruit.get();
@ -1557,8 +1557,8 @@ WML_HANDLER_FUNCTION(recall, /*event_info*/, cfg)
BOOST_FOREACH(unit_map::const_unit_iterator leader, leaders) {
DBG_NG << "...considering " + leader->id() + " as the recalling leader...\n";
map_location loc = cfg_loc;
if ( (leader_filter.null() || unit_filter::matches_filter(leader_filter, *leader, resources::gameboard)) &&
unit_filter::matches_filter(vconfig(leader->recall_filter()), *(*u),map_location(), resources::gameboard) ) {
if ( (leader_filter.null() || unit_filter::matches_filter(leader_filter, *leader, resources::filter_con)) &&
unit_filter::matches_filter(vconfig(leader->recall_filter()), *(*u),map_location(), resources::filter_con) ) {
DBG_NG << "...matched the leader filter and is able to recall the unit.\n";
if(!resources::gameboard->map().on_board(loc))
loc = leader->get_location();
@ -1726,7 +1726,7 @@ WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
}
unit_map::iterator itor;
BOOST_FOREACH(unit &u, *resources::units) {
if ( unit_filter::matches_filter(filter,u, resources::gameboard) ) {
if ( unit_filter::matches_filter(filter,u, resources::filter_con) ) {
u.set_role(cfg["role"]);
found = true;
break;
@ -1763,7 +1763,7 @@ WML_HANDLER_FUNCTION(role, /*event_info*/, cfg)
for(size_t i=0; i < pi->recall_list().size(); ++i) {
unit_ptr u = pi->recall_list()[i];
scoped_recall_unit auto_store("this_unit", player_id, i); //TODO: Should this not be inside the if? Explain me.
if (unit_filter::matches_filter(filter, *u, map_location(), resources::gameboard)) {
if (unit_filter::matches_filter(filter, *u, map_location(), resources::filter_con)) {
u->set_role(cfg["role"]);
found=true;
break;
@ -2287,7 +2287,7 @@ WML_HANDLER_FUNCTION(teleport, event_info, cfg)
const vconfig & filter = cfg.child("filter");
if(!filter.null()) {
for (u = resources::units->begin(); u != resources::units->end(); ++u){
if ( unit_filter::matches_filter(filter,*u, resources::gameboard) )
if ( unit_filter::matches_filter(filter,*u, resources::filter_con) )
break;
}
}

View file

@ -76,7 +76,7 @@ namespace { // Support functions
int match_count = 0;
BOOST_FOREACH(const unit &i, *resources::units)
{
if ( i.hitpoints() > 0 && unit_filter::matches_filter(*u,i, resources::gameboard) ) {
if ( i.hitpoints() > 0 && unit_filter::matches_filter(*u,i, resources::filter_con) ) {
++match_count;
if(counts == default_counts) {
// by default a single match is enough, so avoid extra work
@ -97,7 +97,7 @@ namespace { // Support functions
break;
}
scoped_recall_unit auto_store("this_unit", team->save_id(), t);
if ( unit_filter::matches_filter(*u,*team->recall_list()[t], resources::gameboard) ) {
if ( unit_filter::matches_filter(*u,*team->recall_list()[t], resources::filter_con) ) {
++match_count;
}
}

View file

@ -101,7 +101,7 @@ bool entity_location::matches_unit_filter(const unit_map::const_iterator & un_it
// Filter the unit at the filter location (should be the unit's
// location if no special filter location was specified).
return unit_filter::matches_filter(filter, *un_it, filter_loc_, resources::gameboard) &&
return unit_filter::matches_filter(filter, *un_it, filter_loc_, resources::filter_con) &&
matches_unit(un_it);
}

View file

@ -17,6 +17,7 @@
class config;
#include "filter_context.hpp"
#include "game_board.hpp"
#include "game_data.hpp"
#include "tod_manager.hpp"
@ -25,7 +26,9 @@ class config;
namespace pathfind { class manager; }
struct game_state {
class game_state : public filter_context
{
public:
const config& level_;
game_data gamedata_;
game_board board_;
@ -43,6 +46,9 @@ struct game_state {
void init(int ticks, const config & replay_start);
config to_config() const;
virtual const display_context & get_disp_context() const { return board_; }
virtual const tod_manager & get_tod_man() const { return tod_manager_; }
};
#endif

View file

@ -76,7 +76,7 @@ void teleport_group::get_teleport_pair(
vconfig filter(cfg_.child_or_empty("filter"), true);
vconfig source(cfg_.child_or_empty("source"), true);
vconfig target(cfg_.child_or_empty("target"), true);
if (unit_filter::matches_filter(filter, u, loc, resources::gameboard)) {
if (unit_filter::matches_filter(filter, u, loc, resources::filter_con)) {
scoped_xy_unit teleport_unit("teleport_unit", loc.x, loc.y, *resources::units);

View file

@ -79,6 +79,7 @@ static lg::log_domain log_engine_enemies("engine/enemies");
static void clear_resources()
{
resources::controller = NULL;
resources::filter_con = NULL;
resources::gameboard = NULL;
resources::gamedata = NULL;
resources::persist = NULL;
@ -145,7 +146,7 @@ play_controller::play_controller(const config& level, saved_game& state_of_game,
resources::tod_manager = &gamestate_.tod_manager_;
resources::undo_stack = undo_stack_.get();
resources::units = &gamestate_.board_.units_;
resources::filter_con = &gamestate_;
resources::classification = &saved_game_.classification();
resources::mp_settings = &saved_game_.mp_settings();

View file

@ -67,7 +67,7 @@ namespace wb {
} // namespace wb
// Holds gamestate related objects
struct game_state;
class game_state;
class play_controller : public controller_base, public events::observer, public savegame::savegame_config
{

View file

@ -21,6 +21,7 @@ namespace resources
game_config_manager *config_manager = NULL;
play_controller *controller = NULL;
game_data *gamedata = NULL;
filter_context *filter_con = NULL;
LuaKernel *lua_kernel = NULL;
persist_manager *persist = NULL;
game_display *screen = NULL;

View file

@ -23,6 +23,7 @@ class game_config_manager;
class game_display;
class gamemap;
class game_data;
class filter_context;
class LuaKernel;
class play_controller;
class team;
@ -52,6 +53,7 @@ namespace resources
extern persist_manager *persist;
extern game_classification *classification;
extern game_display *screen;
extern filter_context *filter_con;
extern const mp_game_settings *mp_settings;
extern soundsource::manager *soundsources;
extern std::vector<team> *teams;

View file

@ -858,7 +858,7 @@ static int intf_get_units(lua_State *L)
for (unit_map::const_unit_iterator ui = units.begin(), ui_end = units.end();
ui != ui_end; ++ui)
{
if (!filter.null() && !unit_filter::matches_filter(filter, *ui, ui->get_location(), resources::gameboard))
if (!filter.null() && !unit_filter::matches_filter(filter, *ui, ui->get_location(), resources::filter_con))
continue;
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(ui->underlying_id());
lua_pushvalue(L, 1);
@ -895,11 +895,11 @@ static int intf_match_unit(lua_State *L)
team &t = (*resources::teams)[side - 1];
scoped_recall_unit auto_store("this_unit",
t.save_id(), t.recall_list().find_index(u->id()));
lua_pushboolean(L, unit_filter::matches_filter(filter, *u, map_location(), resources::gameboard));
lua_pushboolean(L, unit_filter::matches_filter(filter, *u, map_location(), resources::filter_con));
return 1;
}
lua_pushboolean(L, unit_filter::matches_filter(filter, *u, u->get_location(), resources::gameboard));
lua_pushboolean(L, unit_filter::matches_filter(filter, *u, u->get_location(), resources::filter_con));
return 1;
}
@ -928,7 +928,7 @@ static int intf_get_recall_units(lua_State *L)
if (!filter.null()) {
scoped_recall_unit auto_store("this_unit",
t.save_id(), t.recall_list().find_index(u->id()));
if (!unit_filter::matches_filter(filter, *u, map_location(), resources::gameboard))
if (!unit_filter::matches_filter(filter, *u, map_location(), resources::filter_con))
continue;
}
new(lua_newuserdata(L, sizeof(lua_unit))) lua_unit(s, u->underlying_id());
@ -2003,7 +2003,7 @@ static int intf_find_cost_map(lua_State *L)
ui != ui_end; ++ui)
{
bool on_map = ui->get_location().valid();
if (on_map && unit_filter::matches_filter(filter, *ui,ui->get_location(), resources::gameboard))
if (on_map && unit_filter::matches_filter(filter, *ui,ui->get_location(), resources::filter_con))
{
real_units. push_back(&(*ui));
}

View file

@ -136,7 +136,7 @@ bool side_filter::match_internal(const team &t) const
if (u.side() != t.side()) {
continue;
}
if (unit_filter::matches_filter(unit_filter, u, u.get_location(), resources::gameboard, flat_)) {
if (unit_filter::matches_filter(unit_filter, u, u.get_location(), resources::filter_con, flat_)) {
found = true;
break;
}
@ -144,7 +144,7 @@ bool side_filter::match_internal(const team &t) const
if(!found && unit_filter["search_recall_list"].to_bool(false)) {
BOOST_FOREACH(const unit_const_ptr & u, t.recall_list()) {
scoped_recall_unit this_unit("this_unit", t.save_id(),t.recall_list().find_index(u->id()));
if(unit_filter::matches_filter(unit_filter, *u, u->get_location(), resources::gameboard, flat_)) {
if(unit_filter::matches_filter(unit_filter, *u, u->get_location(), resources::filter_con, flat_)) {
found = true;
break;
}

View file

@ -154,7 +154,7 @@ bool terrain_filter::match_internal(const map_location& loc, const bool ignore_x
if(cfg_.has_child("filter")) {
const vconfig& unit_filter = cfg_.child("filter");
const unit_map::const_iterator u = units_.find(loc);
if (u == units_.end() || !unit_filter::matches_filter(unit_filter, *u, loc, resources::gameboard, flat_))
if (u == units_.end() || !unit_filter::matches_filter(unit_filter, *u, loc, resources::filter_con, flat_))
return false;
}

View file

@ -1580,7 +1580,7 @@ void unit::add_modification(const std::string& mod_type, const config& mod, bool
{
// Apply SUF.
if (const config &afilter = effect.child("filter"))
if (!unit_filter::matches_filter(vconfig(afilter), *this, loc_, resources::gameboard)) continue;
if (!unit_filter::matches_filter(vconfig(afilter), *this, loc_, resources::filter_con)) continue;
const std::string &apply_to = effect["apply_to"];
const std::string &apply_times = effect["times"];

View file

@ -297,7 +297,7 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
assert(resources::units && resources::gameboard && resources::teams && resources::tod_manager);
if (const config &afilter = cfg.child("filter"))
if ( !unit_filter::matches_filter(vconfig(afilter), *this, loc, resources::gameboard, illuminates) )
if ( !unit_filter::matches_filter(vconfig(afilter), *this, loc, resources::filter_con, illuminates) )
return false;
map_location adjacent[6];
@ -315,7 +315,7 @@ bool unit::ability_active(const std::string& ability,const config& cfg,const map
unit_map::const_iterator unit = units.find(adjacent[index]);
if (unit == units.end())
return false;
if (!unit_filter::matches_filter(vconfig(i), *unit, unit->get_location(), resources::gameboard, illuminates))
if (!unit_filter::matches_filter(vconfig(i), *unit, unit->get_location(), resources::filter_con, illuminates))
return false;
}
}
@ -353,7 +353,7 @@ bool unit::ability_affects_adjacent(const std::string& ability, const config& cf
std::vector<std::string> dirs = utils::split(i["adjacent"]);
if(std::find(dirs.begin(),dirs.end(),adjacent_names[dir]) != dirs.end()) {
if (const config &filter = i.child("filter")) {
if ( unit_filter::matches_filter(vconfig(filter), *this, loc, resources::gameboard, illuminates) )
if ( unit_filter::matches_filter(vconfig(filter), *this, loc, resources::filter_con, illuminates) )
return true;
} else
return true;
@ -371,7 +371,7 @@ bool unit::ability_affects_self(const std::string& ability,const config& cfg,con
const config &filter = cfg.child("filter_self");
bool affect_self = cfg["affect_self"].to_bool(true);
if (!filter || !affect_self) return affect_self;
return unit_filter::matches_filter(vconfig(filter), *this, loc, resources::gameboard, ability == "illuminates");
return unit_filter::matches_filter(vconfig(filter), *this, loc, resources::filter_con, ability == "illuminates");
}
bool unit::has_ability_type(const std::string& ability) const
@ -794,7 +794,7 @@ namespace { // Helpers for attack_type::special_active()
return true;
// Check for a unit match.
if ( !un_it.valid() || !unit_filter::matches_filter(vconfig(filter_child), *un_it, loc, resources::gameboard) )
if ( !un_it.valid() || !unit_filter::matches_filter(vconfig(filter_child), *un_it, loc, resources::filter_con) )
return false;
// Check for a weapon match.
@ -884,7 +884,7 @@ bool attack_type::special_active(const config& special, AFFECTS whom,
continue;
unit_map::const_iterator unit = units.find(adjacent[index]);
if ( unit == units.end() ||
!unit_filter::matches_filter(vconfig(i), *unit, adjacent[index], resources::gameboard) )
!unit_filter::matches_filter(vconfig(i), *unit, adjacent[index], resources::filter_con) )
return false;
}
}

View file

@ -404,7 +404,7 @@ int unit_animation::matches(const display &disp, const map_location& loc,const m
}
std::vector<config>::const_iterator myitor;
for(myitor = unit_filter_.begin(); myitor != unit_filter_.end(); ++myitor) {
if (!unit_filter::matches_filter(vconfig(*myitor), *my_unit, loc, &disp.get_disp_context())) return MATCH_FAIL;
if (!unit_filter::matches_filter(vconfig(*myitor), *my_unit, loc, &disp)) return MATCH_FAIL;
++result;
}
if(!secondary_unit_filter_.empty()) {
@ -413,7 +413,7 @@ int unit_animation::matches(const display &disp, const map_location& loc,const m
if (unit->get_location() == second_loc) {
std::vector<config>::const_iterator second_itor;
for(second_itor = secondary_unit_filter_.begin(); second_itor != secondary_unit_filter_.end(); ++second_itor) {
if (!unit_filter::matches_filter(vconfig(*second_itor), *unit, second_loc, &disp.get_disp_context())) return MATCH_FAIL;
if (!unit_filter::matches_filter(vconfig(*second_itor), *unit, second_loc, &disp)) return MATCH_FAIL;
result++;
}

View file

@ -774,7 +774,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m
vconfig filter = cfg.child("filter");
if(!filter.null()) {
for (u = resources::units->begin(); u != resources::units->end(); ++u) {
if ( unit_filter::matches_filter(filter, *u, resources::gameboard) )
if ( unit_filter::matches_filter(filter, *u, resources::filter_con) )
break;
}
}

View file

@ -17,6 +17,7 @@
#include "config.hpp"
#include "display_context.hpp"
#include "filter_context.hpp"
#include "map_location.hpp"
#include "resources.hpp" //Needed for lua kernel pointer
#include "scripting/lua.hpp" //Needed for lua kernel
@ -31,24 +32,24 @@
#include <boost/foreach.hpp>
namespace { bool internal_matches_filter(const vconfig& filter, const unit & u, const map_location& loc, const display_context * board, bool use_flat_tod); }
namespace { bool internal_matches_filter(const vconfig& filter, const unit & u, const map_location& loc, const filter_context * fc, bool use_flat_tod); }
namespace unit_filter {
bool matches_filter(const vconfig& filter, const unit & u, const display_context * board, bool use_flat_tod)
{ return matches_filter(filter, u, u.get_location(), board, use_flat_tod); }
bool matches_filter(const vconfig& filter, const unit & u, const filter_context * fc, bool use_flat_tod)
{ return matches_filter(filter, u, u.get_location(), fc, use_flat_tod); }
bool matches_filter(const vconfig& cfg, const unit & u, const map_location& loc, const display_context * board, bool use_flat_tod)
bool matches_filter(const vconfig& cfg, const unit & u, const map_location& loc, const filter_context * fc, bool use_flat_tod)
{
bool matches = true;
if(loc.valid()) {
assert(board != NULL);
scoped_xy_unit auto_store("this_unit", loc.x, loc.y, board->units());
matches = internal_matches_filter(cfg, u, loc, board, use_flat_tod);
assert(fc != NULL);
scoped_xy_unit auto_store("this_unit", loc.x, loc.y, fc->get_disp_context().units());
matches = internal_matches_filter(cfg, u, loc, fc, use_flat_tod);
} else {
// If loc is invalid, then this is a recall list unit (already been scoped)
matches = internal_matches_filter(cfg, u, loc, board, use_flat_tod);
matches = internal_matches_filter(cfg, u, loc, fc, use_flat_tod);
}
// Handle [and], [or], and [not] with in-order precedence
@ -62,15 +63,15 @@ bool matches_filter(const vconfig& cfg, const unit & u, const map_location& loc,
// Handle [and]
if(cond_name == "and") {
matches = matches && matches_filter(cond_filter,u, loc, board, use_flat_tod);
matches = matches && matches_filter(cond_filter,u, loc, fc, use_flat_tod);
}
// Handle [or]
else if(cond_name == "or") {
matches = matches || matches_filter(cond_filter,u, loc, board,use_flat_tod);
matches = matches || matches_filter(cond_filter,u, loc, fc,use_flat_tod);
}
// Handle [not]
else if(cond_name == "not") {
matches = matches && !matches_filter(cond_filter,u, loc, board,use_flat_tod);
matches = matches && !matches_filter(cond_filter,u, loc, fc,use_flat_tod);
}
++cond;
@ -82,7 +83,7 @@ bool matches_filter(const vconfig& cfg, const unit & u, const map_location& loc,
namespace { //begin anonymous namespace
bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_location& loc, const display_context * board, bool use_flat_tod)
bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_location& loc, const filter_context * fc, bool use_flat_tod)
{
config::attribute_value cfg_name = cfg["name"];
if (!cfg_name.blank() && cfg_name.str() != u.name()) {
@ -114,9 +115,9 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
}
if(cfg.has_child("filter_location")) {
assert(board != NULL);
assert(fc != NULL);
const vconfig& t_cfg = cfg.child("filter_location");
terrain_filter t_filter(t_cfg, board->units(), use_flat_tod);
terrain_filter t_filter(t_cfg, fc->get_disp_context().units(), use_flat_tod);
if(!t_filter.match(loc)) {
return false;
}
@ -135,8 +136,8 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
if (!cfg_x.blank() || !cfg_y.blank()){
if(cfg_x == "recall" && cfg_y == "recall") {
//locations on the map are considered to not be on a recall list
if ((!board && loc.valid()) ||
(board && board->map().on_board(loc)))
if ((!fc && loc.valid()) ||
(fc && fc->get_disp_context().map().on_board(loc)))
{
return false;
}
@ -317,12 +318,12 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
}
config::attribute_value cfg_defense = cfg["defense"];
if (!cfg_defense.blank() && cfg_defense.to_int(-1) != u.defense_modifier(board->map().get_terrain(loc))) {
if (!cfg_defense.blank() && cfg_defense.to_int(-1) != u.defense_modifier(fc->get_disp_context().map().get_terrain(loc))) {
return false;
}
config::attribute_value cfg_movement = cfg["movement_cost"];
if (!cfg_movement.blank() && cfg_movement.to_int(-1) != u.movement_cost(board->map().get_terrain(loc))) {
if (!cfg_movement.blank() && cfg_movement.to_int(-1) != u.movement_cost(fc->get_disp_context().map().get_terrain(loc))) {
return false;
}
@ -369,7 +370,7 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
}
std::set<int>::const_iterator viewer, viewer_end = viewers.end();
for (viewer = viewers.begin(); viewer != viewer_end; ++viewer) {
bool fogged = board->teams()[*viewer - 1].fogged(loc);
bool fogged = fc->get_disp_context().teams()[*viewer - 1].fogged(loc);
bool hiding = u.invisible(loc/*, false(?) */);
bool unit_hidden = fogged || hiding;
if (visible == unit_hidden) return false;
@ -378,8 +379,8 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
}
if (cfg.has_child("filter_adjacent")) {
assert(board);
const unit_map& units = board->units();
assert(fc);
const unit_map& units = fc->get_disp_context().units();
map_location adjacent[6];
get_adjacent_tiles(loc, adjacent);
vconfig::child_list::const_iterator i, i_end;
@ -393,12 +394,12 @@ bool internal_matches_filter(const vconfig& cfg, const unit & u, const map_locat
for (j = dirs.begin(); j != j_end; ++j) {
unit_map::const_iterator unit_itor = units.find(adjacent[*j]);
if (unit_itor == units.end()
|| !unit_filter::matches_filter(*i, *unit_itor, unit_itor->get_location(), board, use_flat_tod)) {
|| !unit_filter::matches_filter(*i, *unit_itor, unit_itor->get_location(), fc, use_flat_tod)) {
continue;
}
config::attribute_value i_is_enemy = (*i)["is_enemy"];
if (i_is_enemy.blank() || i_is_enemy.to_bool() ==
board->teams()[u.side() - 1].is_enemy(unit_itor->side())) {
fc->get_disp_context().teams()[u.side() - 1].is_enemy(unit_itor->side())) {
++match_count;
}
}

View file

@ -23,17 +23,17 @@
* these to speed up repeated application of the filter.
*/
class display_context;
class filter_context;
class unit;
class vconfig;
struct map_location;
namespace unit_filter {
bool matches_filter(const vconfig& cfg,const unit & u, const map_location& loc, const display_context * board, bool use_flat_tod=false);
bool matches_filter(const vconfig& cfg,const unit & u, const map_location& loc, const filter_context * board, bool use_flat_tod=false);
/// Determine if *this matches @a filter at its current location.
/// (Only use for units currently on the map; otherwise use the overload
/// that takes a location, possibly with a null location.)
bool matches_filter(const vconfig& filter, const unit & u, const display_context* board, bool use_flat_tod=false);
bool matches_filter(const vconfig& filter, const unit & u, const filter_context* board, bool use_flat_tod=false);
}