diff --git a/src/actions/create.cpp b/src/actions/create.cpp index c2849e73cafa..530865bce6ef 100644 --- a/src/actions/create.cpp +++ b/src/actions/create.cpp @@ -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. diff --git a/src/ai/composite/goal.cpp b/src/ai/composite/goal.cpp index 9ddef1c35ab2..c8f24263afb9 100644 --- a/src/ai/composite/goal.cpp +++ b/src/ai/composite/goal.cpp @@ -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()); } diff --git a/src/ai/recruitment/recruitment.cpp b/src/ai/recruitment/recruitment.cpp index 446c27c43445..0df705509762 100644 --- a/src/ai/recruitment/recruitment.cpp +++ b/src/ai/recruitment/recruitment.cpp @@ -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; } diff --git a/src/ai/testing/aspect_attacks.cpp b/src/ai/testing/aspect_attacks.cpp index 56a5d1c78744..0571864211dd 100644 --- a/src/ai/testing/aspect_attacks.cpp +++ b/src/ai/testing/aspect_attacks.cpp @@ -76,7 +76,7 @@ boost::shared_ptr aspect_attacks::analyze_targets() const std::vector 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 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]; diff --git a/src/display.cpp b/src/display.cpp index 44d5cba5a7bf..3183dc878b70 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -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; diff --git a/src/display.hpp b/src/display.hpp index eb153563fdc1..484a7d63366b 100644 --- a/src/display.hpp +++ b/src/display.hpp @@ -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, @@ -164,6 +165,7 @@ class display 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); diff --git a/src/filter_context.hpp b/src/filter_context.hpp new file mode 100644 index 000000000000..7af71c68fce6 --- /dev/null +++ b/src/filter_context.hpp @@ -0,0 +1,43 @@ +/* + Copyright (C) 2014 by Chris Beck + 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 + +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 diff --git a/src/game_board.hpp b/src/game_board.hpp index 42d9adfc75ed..cad1a9958cff 100644 --- a/src/game_board.hpp +++ b/src/game_board.hpp @@ -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: diff --git a/src/game_display.hpp b/src/game_display.hpp index 76c678f91d60..59b5314b6683 100644 --- a/src/game_display.hpp +++ b/src/game_display.hpp @@ -130,6 +130,8 @@ class game_display : public display bool has_time_area() const; + const tod_manager & get_tod_man() const { return tod_manager_; } //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 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 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::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::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; } } diff --git a/src/game_events/conditional_wml.cpp b/src/game_events/conditional_wml.cpp index 4a2ffdbe555a..ba41a0a09287 100644 --- a/src/game_events/conditional_wml.cpp +++ b/src/game_events/conditional_wml.cpp @@ -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; } } diff --git a/src/game_events/entity_location.cpp b/src/game_events/entity_location.cpp index cc0e798981db..310b3c3f2bbf 100644 --- a/src/game_events/entity_location.cpp +++ b/src/game_events/entity_location.cpp @@ -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); } diff --git a/src/game_state.hpp b/src/game_state.hpp index 25928837256b..9629ee901ad3 100644 --- a/src/game_state.hpp +++ b/src/game_state.hpp @@ -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 diff --git a/src/pathfind/teleport.cpp b/src/pathfind/teleport.cpp index 5008232f1c7e..d4fdefac3fad 100644 --- a/src/pathfind/teleport.cpp +++ b/src/pathfind/teleport.cpp @@ -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); diff --git a/src/play_controller.cpp b/src/play_controller.cpp index ddfc34575690..7520f92d9236 100644 --- a/src/play_controller.cpp +++ b/src/play_controller.cpp @@ -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(); diff --git a/src/play_controller.hpp b/src/play_controller.hpp index 4af404bd3510..68e60bc434da 100644 --- a/src/play_controller.hpp +++ b/src/play_controller.hpp @@ -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 { diff --git a/src/resources.cpp b/src/resources.cpp index 7c5b6f3db610..b47fdf8c2e53 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -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; diff --git a/src/resources.hpp b/src/resources.hpp index 2e87b1a84933..51e9dcec77c2 100644 --- a/src/resources.hpp +++ b/src/resources.hpp @@ -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 *teams; diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 1992a608fd9f..75319c31f7ad 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -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)); } diff --git a/src/side_filter.cpp b/src/side_filter.cpp index 050e303afac8..e2b27b790049 100644 --- a/src/side_filter.cpp +++ b/src/side_filter.cpp @@ -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; } diff --git a/src/terrain_filter.cpp b/src/terrain_filter.cpp index 8c38921ef0df..3310ac32e426 100644 --- a/src/terrain_filter.cpp +++ b/src/terrain_filter.cpp @@ -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; } diff --git a/src/unit.cpp b/src/unit.cpp index 931d95fb5056..444d4a7ad8f1 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -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"]; diff --git a/src/unit_abilities.cpp b/src/unit_abilities.cpp index 8343f7c67637..c7a54357f3b8 100644 --- a/src/unit_abilities.cpp +++ b/src/unit_abilities.cpp @@ -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 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; } } diff --git a/src/unit_animation.cpp b/src/unit_animation.cpp index f8c9fa52c719..1ccb0a93116b 100644 --- a/src/unit_animation.cpp +++ b/src/unit_animation.cpp @@ -404,7 +404,7 @@ int unit_animation::matches(const display &disp, const map_location& loc,const m } std::vector::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::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++; } diff --git a/src/unit_display.cpp b/src/unit_display.cpp index 4540d0bc9586..d61e5d0dfb34 100644 --- a/src/unit_display.cpp +++ b/src/unit_display.cpp @@ -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; } } diff --git a/src/unit_filter.cpp b/src/unit_filter.cpp index 69815554a10e..b5e5398635bc 100644 --- a/src/unit_filter.cpp +++ b/src/unit_filter.cpp @@ -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 -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::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; } } diff --git a/src/unit_filter.hpp b/src/unit_filter.hpp index da337a5ce473..1d8d8b757173 100644 --- a/src/unit_filter.hpp +++ b/src/unit_filter.hpp @@ -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); }